■ 内臓 A/Dコンバータの読込み                              
     PIC16、18、dsPICシリーズでは8〜12ビットの内臓A/Dコンバータが内臓されているPICがあります。

 ■ CCSコンパイラ
     CCSコンパイラでははA/Dコンバータ読込みに関して以下の4つの例を紹介します。

     (1) 8ビットA/Dコンバータ出力を8個のLEDで表示
     (2) 8ビットA/Dコンバータ出力を液晶に表示
     (3) 基準電圧による正確な10ビットA/D変換
     (4) AD変換を2つ使用した高分解能10ビットA/D変換

 ■ C18コンパイラ
     (1) 入力電圧を液晶に表示(PIC18F4550)
     (2) 入力電圧を液晶に表示(PIC18F452)

 ■ C30コンパイラ dsPIC編
     (1) 入力電圧を液晶に表示(dsPIC30F2012)
     (2) 入力電圧を液晶に表示(dsPIC30F4013)

 ■ C30コンパイラ  PIC24編
    入力電圧を液晶に表示(PIC24FJ64GA002)


 ■ C32コンパイラ PIC32MX編
   入力電圧を液晶に表示(PIC32MX460F512L)


 ■ CCSコンパイラ


  A/Dコンバータの読み込み方はすべて同じで以下のようになります。(詳細 コンパイラのヘルプ参照)
 

記載
順番
ソースコードへの記載要領
1. プリプロセッサにおいて使用するPICのヘッダーファイルをインクルードします.
すぐあとの行にA/Dコンバータの分解能に関する記載をおこなます
  #include <pic16f877.h>
  #device ADC=10
2. 使用するクロック周波数に関する記載をおこなう   #use delay(clock=20000000)
3. A/D変換した値を格納する変数を設定します
8ビットのA/Dの場合はunsigned int型を、10〜12ビットのA/Dの場合は long int型またはunsigned long int型の整数を設定します。
  unsigned int   Advalue;
4. A/D変換に関係するポートをアナログポートとして使用するのか、デジタルポートとして使用するのか、またA/D変換する際の基準電圧端子として使用するかといった設定をおこないます。   setup_adc__ports( ALL_ANALOG );
5. PICの内臓A/Dコンバータは逐次比較型です。変換に際し使用するクロックとして何をつかうのかを main関数のはじめで設定します。 通常は内部クロックをつかいます。    setup_adc(ADC_CLOCK_INTERNAL);
6. どのポートのアナログ値を読むのか指定します。PICは複数のA/D変換ができるポートをもっていますが、逐次比較レジスタ、D/A変換器、及び これらの制御部を1つしかもっていいないので切り替えて使います。同時には読み込めません。   set_adc_channel(2);
7. チャンネルを切り替えた後、A/D変換されたデジタル値がセットされるまでの時間(トータルセトリング時間)+αの時間だけ待ちます    delay_us(50);
  8.  A/D変換された値を読み込み、変数にセットします。  read_adc();の戻り値についてコンパイラのリファレンスマニュアルには
 Returns: Either a 8 or 16 bit int depending on #DEVICE ADC= directive.
とあります。 実際に観測してみると戻ってくるのは符合なし整数です。戻り値の変数の型は符号なしの整数にするようにしましょう。 10ビットAD変換の時は変数の型をlong int (16ビット)にするので整数でも符号なし整数でも問題は発生しません。しかし、8ビットAD変換の時変数の型をint型(8ビット)にすると基準電圧の1/2以上の値に対し戻り値は負となってしまいます。(2)8ビットA/Dコンバータ出力を液晶に表示 を参照して下さい。 
  Advalue = read_adc(); 



     

以下のプログラム例の中にある液晶表示器制御ライブラリ 1llcd_lib.cは 後閑哲也さんが設計されたものです。


(1) 8ビットA/Dコンバータ出力を8個のLEDで表示

  <試作品仕様>
   ・ 可変抵抗器で0〜5Vの電圧をつくり、ポートAN0に入力すること
   ・ AN0に入力された電圧をPICの電源電圧+5Vを比較基準電圧として8ビットのA/Dコンバータで読み込むこと
   ・ A/D変換された8ビット値を LSB(第0位ビット)→RB0、第1位ビット→RB1、…… MSB(第7位ビット)→RB7、
     となるように対応させ、A/Dコンバータの値にしたがってLEDを点滅させること
   ・ 入力電圧が0Vの時LEDはすべてOFF、5Vの時はすべて点灯させること 
   


  <試作品回路図>
    PIC16F877をつかった場合の回路図を以下に示します。(→回路図のPDFファイル

 


  <試作品外観>

     

          

   <プログラム例>

/* ----------------------------------------------------------------------------------------- PIC16F877  内臓ADコンバータを8ビットの分解能で使ってアナログ電圧を読み込み値を8個のLEDで表示する ------------------------------------------------------------------------------------------- */ #include "16f877.h" #device ADC=8 // 10ビットにもなるADコンバータではあるが 8ビットのADコンバータにセット #use delay(clock=20000000) #FUSES HS,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP #byte port_b=6 //Bポートレジスタ(6番地)を 変数port_bに対応させる main(){ unsigned int unsignedintX; set_tris_b(0); //Bポートの端子をすべて出力モード "0" に設定 setup_adc_ports(ALL_ANALOG); //AN0〜AN7すべてをA/D変換入力ポートに設定 setup_adc(ADC_CLOCK_INTERNAL); //逐次変換して比較する時、内部クロックを使用する while(1) { set_adc_channel(0); // チャンネルAN0のADコンバータ変換開始 delay_us(50); //A/D変換されたデジタル値がセットされるまでの時間(トータルセトリング時間)+αの時間だけ待ちます  unsignedintX = read_adc(); //A/D変換された値を読み込み、符号なし整数の変数にセットします port_b = ~(unsignedintX); //BポートにAD変換されたデジタル値を反転して出力する } return 0; }

 


(2) 8ビットA/Dコンバータ出力を液晶に表示
   AD変換された値を整数でよみとると比較電圧の1/2より大きい電圧に対しては値が負になると同時に電圧が大きく
  なるにしたがって値の絶対値が減少していきます。
    入力電圧           小               1/2                                     大
     整数         0    1    2 ……  125  126  127  -128   -127  -126 -125    ……        -3    -2     -1
    符号なし整数          0    1    2  ……     125  126  127    128    129    130   131                  253  254  255
     

    この問題は8ビットA/D変換の時変数をint型(8ビット)にした場合に発生します。 read_adc();の戻り値は符号
   なしの整数なので変数は符号なしの整数にした方がよいと思います。 尚、変数の型を long int型(16ビット)に
   しておけば比較電圧の1/2以上で負になるこのトラブルはA/Dが10ビット変換の場合も含め発生しません

   

  <試作品仕様>
   ・ 可変抵抗器で0〜5Vの電圧をつくり、ポートAN0に入力すること
   ・ AN0に入力された電圧をPICの電源電圧+5Vを比較基準電圧として8ビットのA/Dコンバータで読み込むこと
   ・ A/D変換された値を(符号付)整数で受け取り液晶の1行目に(符号付)整数で表示すること。
   ・ A/D変換された値を符号なし整数で受け取り液晶の2行目に符号なし整数として表示すること
   ・ A/D変換された8ビット値を LSB(第0位ビット)→RB0、第1位ビット→RB1、…… MSB(第7位ビット)→RB7、
     となるように対応させ、A/Dコンバータの値にしたがってLEDを点滅させること
   ・ 入力電圧が0Vの時LEDはすべてOFF、5Vの時はすべて点灯させること 
  

  <試作品回路図>
    PIC16F877をつかった場合の回路図を以下に示します。(→回路図のPDFファイル

 

          

   <プログラム例>
/*
------------------------------------------------------------------
PIC16F877
 ADコンバータの値を整数と符号なし整数の両方で呼んで液晶に比較表示する
 内臓ADコンバータを8ビットの分解能で使ってアナログ電圧を読み込み値を8個のLEDで表示する
--------------------------------------------------------------------
*/


#include "16f877.h"
#device ADC=8
#use delay(clock=20000000)
#FUSES  HS,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP
#byte   port_b=6                //Bポートレジスタ(6番地)を 変数port_bに対応させる

#use fast_io(D)
//////// Port define and link LCD library 
#define mode     0

//   液晶
#define input_x         input_D
#define output_x        output_D
#define set_tris_x      set_tris_D
#define rs PIN_D2       //chip select
#define stb PIN_D0      //strobe

#include <1lcd_lib.c>



main(){
        int     intX;
        unsigned int unsignedintX;
        set_tris_b(0);
        setup_adc_ports(ALL_ANALOG);    //AN0〜AN7すべてをA/D変換入力ポートに設定
        setup_adc(ADC_CLOCK_INTERNAL);  //逐次変換して比較する時、内部クロックを使用する



        lcd_init();
        lcd_cmd(0b00001100);                    // カーソル:OFF    ブリンク:OFF
        lcd_clear();
        printf(lcd_data,"start!!");
        delay_ms(2000);
        
        lcd_clear();

        while(1)
        {
        
        set_adc_channel(0);             // チャンネルAN0のADコンバータ変換開始
        delay_us(50);                   //A/D変換されたデジタル値がセットされるまでの時間(トータルセトリング時間)+αの時間だけ待ちます 
        intX = read_adc();              //A/D変換された値を読み込み、整数の変数にセットします
        unsignedintX = read_adc();      //A/D変換された値を読み込み、符号なし整数の変数にセットします

        lcd_clear();// 液晶オールクリア
        printf(lcd_data,"intX=%d",intX);//読み込んだ値を

        lcd_cmd(0xC0);//2行目の先頭へ
        printf(lcd_data,"unsignedintX=%u",unsignedintX);
        port_b = ~(unsignedintX);       //BポートにAD変換されたデジタル値を出力する

        delay_ms(300);
        
        }

        
        return 0;

}

//---------------------------------------------------------------------------

//**************************************
//インクルードファイル    1lcd_lib.c
//このファイルは後閑哲也さんが設計されたものです
//**************************************


///////////////////////////////////////////////
//  液晶表示器制御ライブラリ
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去



//////// データ出力サブ関数
void lcd_out(int code, int flag)
{
        output_x((code & 0xF0) | (input_x() & 0x0F));
        if (flag == 0)
                output_high(rs);                //表示データの場合
        else
                output_low(rs);                 //コマンドデータの場合
        delay_cycles(4);                        //NOP 1         
        output_high(stb);                       //strobe out
        delay_cycles(8);                        //NOP 2
        output_low(stb);                        //reset strobe
}
//////// 1文字表示関数
void lcd_data(int asci)
{
        lcd_out(asci, 0);                       //上位4ビット出力
        lcd_out(asci<<4, 0);            //下位4ビット出力
        delay_us(50);                           //50μsec待ち
}
/////// コマンド出力関数
void lcd_cmd(int cmd)
{
        lcd_out(cmd, 1);                        //上位4ビット出力
        lcd_out(cmd<<4, 1);                     //下位4ビット出力
        delay_ms(2);                            //2msec待ち
}
/////// 全消去関数
void lcd_clear()
{
        lcd_cmd(0x01);                          //初期化コマンド出力
        delay_ms(15);                           //15msec待ち
}
/////// 初期化関数
void lcd_init()
{
        set_tris_x(mode);                       //モードセット
        delay_ms(15);
        lcd_out(0x30, 1);                       //8bit mode set
        delay_ms(5);
        lcd_out(0x30, 1);                       //8bit mode set
        delay_ms(1);
        lcd_out(0x30, 1);                       //8bit mode set
        delay_ms(1);
        lcd_out(0x20, 1);                       //4bit mode set
        delay_ms(1);
        lcd_cmd(0x2E);                          //DL=0 4bit mode
        lcd_cmd(0x08);                          //display off C=D=B=0
        lcd_cmd(0x0D);                          //display on C=D=1 B=0
        lcd_cmd(0x06);                          //entry I/D=1 S=0
        lcd_cmd(0x02);                          //cursor home
}

 <動作結果>

入力電圧が2.5V以下の場合
  整数 と 符号なし整数は同じ値となる
入力電圧が2.5v以上の場合
  整数と符号なし整数は異なる値となる




(3) 基準電圧による正確な10ビットA/D変換  

  <試作品仕様>
   ・ 可変抵抗器で0〜5Vの電圧をつくり、ポートAN0に入力すること
   ・ AN0に入力された電圧を電源変動、温度変動の少ない比較基準電圧をもちいて10ビットのA/Dコンバータで
     読み込むこと
   ・ A/D変換されたデジタル変換値を液晶の1行目に10進数で表示すること。
   ・ また液晶の2行目には入力された電圧を 単位 V で表示すること

         
  <試作品回路図>  (→回路図のPDFファイル
    PIC16F877をつかった場合の回路図を以下に示します。 安定した基準電圧素子としてナショゼミのLM385
   つかった例を以下に示します。下図の場合RA3に入力される基準電圧はデータシートにある計算式より
     Vref = 1.24 ×(R3/R2 + 1)  =  1.24 × ( 220kΩ/100KΩ + 1 )  = 3.968 V
       となります。


 

          

   <プログラム例>

/* ------------------------------------------------------------------ PIC16F877 ADコンバータの値を符号なし整数で読み込んで 10ビット値と電圧値を液晶に比較表示する  基準電圧はLM385で安定化された3.968Vを使用する -------------------------------------------------------------------- */ #include "16f877.h" #device ADC=10 #use delay(clock=20000000) #FUSES HS,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP #byte port_b=6 //Bポートレジスタ(6番地)を 変数port_bに対応させる #use fast_io(D) //////// Port define and link LCD library #define mode 0 // 液晶 #define input_x input_D #define output_x output_D #define set_tris_x set_tris_D #define rs PIN_D2 //chip select #define stb PIN_D0 //strobe #include <1lcd_lib.c> main(){ unsigned long int adValue; set_tris_b(0); setup_adc_ports(AN0_AN1_VSS_VREF); //AN0 AN1をAN3に入力される電圧を基準にA/D変換ポートに設定 setup_adc(ADC_CLOCK_INTERNAL); //逐次変換して比較する時、内部クロックを使用する lcd_init(); lcd_cmd(0b00001100); // カーソル:OFF ブリンク:OFF lcd_clear(); printf(lcd_data,"start!!"); delay_ms(2000); lcd_clear(); while(1) { set_adc_channel(0); // チャンネルAN0のADコンバータ変換開始 delay_us(50); //A/D変換されたデジタル値がセットされるまでの時間(トータルセトリング時間)+αの時間だけ待ちます  adValue = read_adc(); //A/D変換された値を読み込み、符号なし整数の変数にセットします lcd_clear();// 液晶オールクリア printf(lcd_data,"adValue=%lu",adValue);//読み込んだ値を lcd_cmd(0xC0);//2行目の先頭へ printf(lcd_data,"Vin=%4.3f V",3.968*((float)AdValue/1023)); //10ビット値を電圧値に換算 delay_ms(300); } return 0; } //--------------------------------------------------------------------------- //************************************** //インクルードファイル 1lcd_lib.c //このファイルは後閑哲也さんが設計されたものです //************************************** /////////////////////////////////////////////// // 液晶表示器制御ライブラリ // 内蔵関数は以下 // lcd_init() ----- 初期化 // lcd_cmd(cmd) ----- コマンド出力 // lcd_data(chr) ----- 1文字表示出力 // lcd_clear() ----- 全消去 //////// データ出力サブ関数 void lcd_out(int code, int flag) { output_x((code & 0xF0) | (input_x() & 0x0F)); if (flag == 0) output_high(rs); //表示データの場合 else output_low(rs); //コマンドデータの場合 delay_cycles(4); //NOP 1 output_high(stb); //strobe out delay_cycles(8); //NOP 2 output_low(stb); //reset strobe } //////// 1文字表示関数 void lcd_data(int asci) { lcd_out(asci, 0); //上位4ビット出力 lcd_out(asci<<4, 0); //下位4ビット出力 delay_us(50); //50μsec待ち } /////// コマンド出力関数 void lcd_cmd(int cmd) { lcd_out(cmd, 1); //上位4ビット出力 lcd_out(cmd<<4, 1); //下位4ビット出力 delay_ms(2); //2msec待ち } /////// 全消去関数 void lcd_clear() { lcd_cmd(0x01); //初期化コマンド出力 delay_ms(15); //15msec待ち } /////// 初期化関数 void lcd_init() { set_tris_x(mode); //モードセット delay_ms(15); lcd_out(0x30, 1); //8bit mode set delay_ms(5); lcd_out(0x30, 1); //8bit mode set delay_ms(1); lcd_out(0x30, 1); //8bit mode set delay_ms(1); lcd_out(0x20, 1); //4bit mode set delay_ms(1); lcd_cmd(0x2E); //DL=0 4bit mode lcd_cmd(0x08); //display off C=D=B=0 lcd_cmd(0x0D); //display on C=D=1 B=0 lcd_cmd(0x06); //entry I/D=1 S=0 lcd_cmd(0x02); //cursor home }

 <動作結果>







 C18編  外部リファレンスによるAD変換

<試作品回路図>PIC18F87K90をつかった場合の回路図を以下に示します。(→回路図のPDFファイル






<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています





          

   <プログラム例>

/*
AD コンバータ 12ビットAD 
                                                                                        PC18F87K90              
*/

#include <p18f87K90.h>

#include <stdio.h>
#include <delays.h>
#include <timers.h>
#include <adc.h>

#include "1lcd_lib_C18.h"
#include "1lcd_lib_C18.c"


#pragma config FOSC = XT                //FOSC = HS // システムクロック=1MHz 
#pragma config XINST = OFF
#pragma config  WDTEN = OFF     //ウォッドックタイマ OFF



unsigned int Count_10msec;

        char tempBuf[17];       //液晶表示データの一時保存レジスタ

    long int ADread;
        char str[17];
        char str2[30];
        float Vin,Vin1000;
        long int Vin1000i;
        int Vi,Vf;




void delay_ms (long int cycle)  // CCSコンパイラと同じ delay_ms(long int) 関数を設計
{
        long int i = 0;
        for (i = 0; i < cycle; i++)Delay10TCYx(25);      //  25 x 40μsec = 1000μsec // Delay10TCY():40μsec  
}



void lcd_printf(char* str)      //液晶表示補助関数
{
        while(*str)     //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;
        }       
}




void Ad_Func()  //AD変換読込み & 表示
{
    
        
                SetChanADC(ADC_CH0);    //チャンネルを切り替える場合
        ConvertADC();
        while( BusyADC());      //AD変換が終わるまで待つ
        ADread = ReadADC();     //AD変換値読込み
                                                
                                //液晶へ表示
        lcd_clear();
        sprintf(str,"ADread=%ld",ADread);
        lcd_printf(&str[0]);//  AD変換読込み値を液晶に1行目に表示    読込み値:1023(at 5V)

        Vin = (float)ADread/4095*5.0;
        Vi = (int)Vin;
        Vf =(int)( (Vin - (int)Vin)*100);

        sprintf(&str2[0],"Vin[v]=%d.%d",Vi,Vf); // %f(浮動少数)は未サポート
        lcd_cmd(0xC0);//2行目の先頭へ
        lcd_printf(&str2[0]);// AD変換読込み値を液晶に2行目に表示    読込み値:1023(at 5V)  
        
      
}


#pragma interrupt my_Func               // 10msec タイマ1 インターバル割り込み
#pragma code isrcode = 0x08
void isr_direct(void)
{ _asm goto my_Func _endasm }
#pragma code
void my_Func(void)
{
        
        LATJbits.LATJ0 = 0;
        
        PIR1bits.TMR1IF = 0;    // タイマ1割り込みフラグをクリアする
        WriteTimer1(15536);     // 1μsec × 4 × 1 × 50000 = 200000μsec = 200msec (at システムクロック1MHz)
                                                        // 256×256 - 50000 = 15536
        Ad_Func();

        LATJbits.LATJ0 = 1;
}



void main (void)
{
        unsigned char channel=0x00,config1=0x00,config2=0x00,config3=0x00,portconfig=0x00;


        TRISD = 0;
        TRISJ = 0;

        TRISAbits.TRISA0 = 1;
        TRISAbits.TRISA2 = 1;
        TRISAbits.TRISA3 = 1;

        ANCON0 = 0b00001101;    //RA0
        ANCON1 = 0;
        ANCON2 = 0;



    config1 =                                   //ADCON0: A/D CONTROL REGISTER 0
                        ADC_CH0 |                       //AD変換するのチャンネル選択(PIC18Fは同時に複数のAD変換はできない)                
                        ADC_INT_OFF |           //AD変換での割込み使用の有無
                        ADC_REF_VDD_INT_VREF_2 |
//                      ADC_REF_VDD_VREFPLUS |  //Vref+の設定   外部Vref電圧 
                        ADC_REF_VDD_VSS ;       //Vref-の設定   PICの0V 

                                                                //ADCON1: A/D CONTROL REGISTER 1

        config2 =                                       //ADCON2: A/D CONTROL REGISTER 2
                        ADC_FOSC_2 |            //AD変換用クロック  システムクロックの1/2 
                        ADC_RIGHT_JUST |        //変換結果の保存方法 左詰め 
                        ADC_2_TAD ;                     //AD変換のアクイジションタイム選択 変換クロック時間(=1Tad)×2Tad

        OpenADC(config1,config2,portconfig);



        //ADCON1レジスタ// 電源電圧リファレンスでない場合はADCON1レジスタの書き込みが必要である。 C18のバグ?
        ADCON1bits.TRIGSEL1 = 0;        //
        ADCON1bits.TRIGSEL0 = 0;
        ADCON1bits.VCFG1 = 0;   //01: 外部リファレンス//(参考:10: Vref = 2.048v)
        ADCON1bits.VCFG0 = 1;
        ADCON1bits.VNCFG = 0;   //Vref-: AVss   //PICのGND 
                                                        // ★内部リファレンス 及び外部リファレンス共に Vref- を0Vに接続する必要なし
                                                        // ★差動入力の場合のみ必要
                                                        // ★電源電圧がリファレンス電圧以下になると まったくおかしなAD変換値となる。 
                                                       
        ADCON1bits.CHSN2 = 0;   //Vref- としてAVss と外部Vref-を選択した場合は000を選択
        ADCON1bits.CHSN1 = 0;
        ADCON1bits.CHSN0 = 0;


        lcd_init();                                     // LCD初期化
        lcd_cmd(0b00001100);        // カーソル:OFF    ブリンク:OFF
        lcd_clear();
        sprintf(&tempBuf[0],"AD Converter !!"); //文字列としてバッファーに収納
        lcd_printf(&tempBuf[0]);

        lcd_cmd(0xC0);//2行目の先頭へ
        sprintf(&tempBuf[0],"     Start2 !!");  //文字列としてバッファーに収納
        lcd_printf(&tempBuf[0]);



         while (1)
    {
                Ad_Func();
                delay_ms(200);
    }


}




//************************************************
//インクルードファイル    1lcd_lib_C18.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリを
//C18コンパイラ用に変更したものです。
//************************************************
#define         lcd_port                LATD    //DataOutPort    pin : 上位4bit
#define         lcd_stb                 LATDbits.LATD3  //stb OutPort  
#define         lcd_rs                  LATDbits.LATD2  // rs OutPort
#define         port_Mode               TRISD   // Port Mode set                        


void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_out(char code, char flag);





//***********************************************
//インクルードファイル    1lcd_lib_C18.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリを
//C18コンパイラ用に変更したものです。
//***********************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C18コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//////////////////////////////////////////////

#include        "delays.h"
#include        "1lcd_lib_C18.h"


//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        port_Mode = 0;  // PIC側の DataPort、stbPort、 rsPort を出力モードに設定
        lcd_port = code & 0xF0;
        if (flag == 0)
                lcd_rs = 1;                     //表示データの場合
        else
                lcd_rs = 0;                     //コマンドデータの場合
        
        Delay10TCYx(1);                 //10NOP 
        lcd_stb = 1;                    //strobe out
        Delay10TCYx(1);                 //10NOP
        lcd_stb = 0;                    //reset strobe
}


//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);                       //上位4ビット出力
        lcd_out(asci<<4, 0);            //下位4ビット出力
        Delay10TCYx(50);                        //500NOP (50μsec待ち at 40MHz)
}


/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                //上位4ビット出力
        lcd_out(cmd<<4, 1);             //下位4ビット出力
        if((cmd & 0x03) != 0)
                Delay10KTCYx(2);                //2msec待ち at 40MHz
        else
                Delay10TCYx(50);                //50usec待ち at 40MHz
}


/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  //初期化コマンド出力
//  Delay10KTCYx(15);           //15msec待ち at 40MHz
}


/////// 初期化関数
void lcd_init(void)
{
        lcd_out(0x30, 1);               //8bit mode set
        Delay10KTCYx(5);                //5msec待ち at 40MHz
        lcd_out(0x30, 1);               //8bit mode set
        Delay10KTCYx(1);                //1msec待ち at 40MHz
        lcd_out(0x30, 1);               //8bit mode set
        Delay10KTCYx(1);                //1msec待ち at 40MHz
        lcd_out(0x20, 1);               //4bit mode set
        Delay10KTCYx(1);                //1msec待ち at 40MHz
        lcd_cmd(0x2E);                  //DL=0 4bit mode
        lcd_cmd(0x08);                  //display off C=D=B=0
        lcd_cmd(0x0D);                  //display on C=D=1 B=0
        lcd_cmd(0x06);                  //entry I/D=1 S=0
        lcd_cmd(0x01);                  //all clear
}






 <実行結果>
 ・リファレンス電圧が電源電圧以下の場合は 妥当な実験結果がえられた。 すなわち 電源電圧がリファレンス電圧2.4V以下になると まったくおかしなAD変換値となる
 ・外部リファレンス電圧でのAD変換の場合、 Vref- 端子は GNDに接続する必要はない。 ソフトでの設定だけでよい。
 ・リファレンス電圧の出力インピーダンスは低くなければならない。
 ・電圧測定端子に直接基準電圧素子LM285-1.2をつないでもAN端子の入力インピーダンスが高いので基準電圧降下は得られなかった。 20KΩのダミー抵抗を接続すると1.2vの電圧降下は得られる。
 ・PIC電圧が低下した時の液晶(+5.0V)との信号電圧レベル変換レベルシフターとして、 3.0v電源の74HC4050は有効であった。

AD変換値 理論値
被測定電圧\PIC電源電圧 1.6v 1.8v 2.0v 2.5v 3.0v 3.3v 5.0v     
0.5v 3793 3860 3888 845 810 810 880 4095 × 0.5/2.4 = 853
1.0v 3807 3883 3916 1653 1668 1681 1700 4095 × 10/2.4 = 1706
1.8v 3825 3900 3944 2948 2971 2950 2953 4095 × 1.8/2.4 = 3071







(4) A/D変換を2つ使用した高分解能10ビットA/D変換

  <試作品仕様>
   ・ 可変抵抗器で0〜5Vの電圧をつくり、ポートAN0に入力すること
   ・ 測定電圧が小さな値においてもの相対的にA/Dの分解能を高めること
   ・ AN0、AN1でA/D変換されたデジタル変換値を液晶の1行目に10進数で表示すること。
   ・ 液晶の2行目には AD変換された10ビット値と入力された電圧をボルト(小数点以下3桁)で表示すること


  <試作品回路図>   (→回路図のPDFファイル
    PIC16F877をつかった場合の回路図を以下に示します。単電源で特性のよいオペアンプLM2904をもちいて10倍の
   アンプをつくり測定電圧を増幅してこの出力をAN1に接続しました。 LM2904を+5Vの単電源で使用する場合リニア
   リティがよいのは出力が3.5V程度までなので 出力電圧で0〜2.5Vの範囲のAN1入力電圧を活用することとしました。
   こうすることで測定電圧の0〜0.25Vが高分解能でA/D変換できることになります。

 

          

   <プログラム例>

/* ------------------------------------------------------------------ PIC16F877 小さな値はアナログアンプ(ゲイン=10倍)で増幅後AD変換してよむ  ADコンバータを2つ使い小さな電圧検出の分解能をあげる -------------------------------------------------------------------- */ #include "16f877.h" #device ADC=10 #use delay(clock=20000000) #FUSES HS,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP #byte port_b=6 //Bポートレジスタ(6番地)を 変数port_bに対応させる #use fast_io(D) //////// Port define and link LCD library #define mode 0 // 液晶 #define input_x input_D #define output_x output_D #define set_tris_x set_tris_D #define rs PIN_D2 //chip select #define stb PIN_D0 //strobe #include <1lcd_lib.c> main(){ unsigned long int A0,A1,AT; set_tris_b(0); setup_adc_ports(ALL_ANALOG); //AN0 AN1をAN3に入力される電圧を基準にA/D変換ポートに設定 setup_adc(ADC_CLOCK_INTERNAL); //逐次変換して比較する時、内部クロックを使用する lcd_init(); lcd_cmd(0b00001100); // カーソル:OFF ブリンク:OFF lcd_clear(); printf(lcd_data,"start!!"); delay_ms(2000); lcd_clear(); while(1) { set_adc_channel(0); // チャンネルAN0のADコンバータ変換開始 delay_us(50); //A/D変換されたデジタル値がセットされるまでの時間(トータルセトリング時間)+αの時間だけ待ちます  A0 = read_adc(); //A/D変換された値を読み込み、符号なし整数の変数にセットします set_adc_channel(1); // チャンネルAN1のADコンバータ変換開始 delay_us(50); //A/D変換されたデジタル値がセットされるまでの時間(トータルセトリング時間)+αの時間だけ待ちます  A1 = read_adc(); //A/D変換された値を読み込み、符号なし整数の変数にセットします lcd_clear();// 液晶オールクリア printf(lcd_data,"A0=%lu A1=%lu",A0,A1);//読み込んだ値を表示 if(A0>= 52) { AT = A0; //5%以上ならA0から読み込んだ値をつかう   1023 × 0.05 = 51.15 //5V×0.05 = 0.25V     0.25V × 10(=アンプゲイン) = 2.5V // 2.5V  <  3.5V(アンプ飽和電圧) lcd_cmd(0xC0);//2行目の先頭へ printf(lcd_data,"AT=%lu V=%4.3f",AT,5*((float)AT/1023)); //10ビット値を電圧値に換算 } else { AT = A1; lcd_cmd(0xC0);//2行目の先頭へ printf(lcd_data,"AT=%lu V=%4.3fV",AT,5*((float)AT/1023/10)); //10ビット値を電圧値に換算 } delay_ms(300); } return 0; } //--------------------------------------------------------------------------- //************************************** //インクルードファイル 1lcd_lib.c //このファイルは後閑哲也さんが設計されたものです //************************************** /////////////////////////////////////////////// // 液晶表示器制御ライブラリ // 内蔵関数は以下 // lcd_init() ----- 初期化 // lcd_cmd(cmd) ----- コマンド出力 // lcd_data(chr) ----- 1文字表示出力 // lcd_clear() ----- 全消去 //////// データ出力サブ関数 void lcd_out(int code, int flag) { output_x((code & 0xF0) | (input_x() & 0x0F)); if (flag == 0) output_high(rs); //表示データの場合 else output_low(rs); //コマンドデータの場合 delay_cycles(4); //NOP 1 output_high(stb); //strobe out delay_cycles(8); //NOP 2 output_low(stb); //reset strobe } //////// 1文字表示関数 void lcd_data(int asci) { lcd_out(asci, 0); //上位4ビット出力 lcd_out(asci<<4, 0); //下位4ビット出力 delay_us(50); //50μsec待ち } /////// コマンド出力関数 void lcd_cmd(int cmd) { lcd_out(cmd, 1); //上位4ビット出力 lcd_out(cmd<<4, 1); //下位4ビット出力 delay_ms(2); //2msec待ち } /////// 全消去関数 void lcd_clear() { lcd_cmd(0x01); //初期化コマンド出力 delay_ms(15); //15msec待ち } /////// 初期化関数 void lcd_init() { set_tris_x(mode); //モードセット delay_ms(15); lcd_out(0x30, 1); //8bit mode set delay_ms(5); lcd_out(0x30, 1); //8bit mode set delay_ms(1); lcd_out(0x30, 1); //8bit mode set delay_ms(1); lcd_out(0x20, 1); //4bit mode set delay_ms(1); lcd_cmd(0x2E); //DL=0 4bit mode lcd_cmd(0x08); //display off C=D=B=0 lcd_cmd(0x0D); //display on C=D=1 B=0 lcd_cmd(0x06); //entry I/D=1 S=0 lcd_cmd(0x02); //cursor home }

 <動作結果>
  A0(=18)がアンプ(ゲイン10倍)を経ない電圧をよんだA/D変換の10ビット値で、A1(=175)がアンプ(ゲイン10倍)を
  経た後によんだA/D変換の10ビット値です。分解能が1桁あがっていることがわかります。
   アナログのアンプを追加して2つのA/DコンバータでA/D変換をおこなうことは、小さな値の測定値に対しても相対的
  精度を要求される場合に有効な方法だと思います。12ビット、16ビットのA/Dコンバータを外付けするとPICとのインター
  フェース、処理スピード、コスト等いろいろな問題が発生してきます。






■ C18コンパイラ

  C18コンパイラの場合、内臓ADコンバータからのAD変換値を読込みの基本的な流れは以下のようになります。

    @ OpenADC() 関数で SFRの設定をおこなう。但し一部のPICでは直接のレジスタ書き込みも必要となる。
    A SetChanADC()関数で 読み込みのチャンネルを選択する。
    B ConvertADC()関数で 読み込みを開始する。
    C BusyADC()関数で AD変換が完了するのを待つ(戻り値が"0"になるまで待つ)
    D ReadADC()関数で AD変換値を読み込む
    E CloseADC()関数で AD変換をDisableにする



 (1)入力電圧を液晶に表示(PIC18F4550)
  PIC18F4550の内臓ADコンバータからAD変換値を読込み、値を液晶に表示した例を紹介します。 PICの種類によって
 OpenADC()関数の引数、及び引数の数が異なります。PIC18F4550の場合はSFRのADCON0、ADCON1、ADCON2レジスタ
 すべての設定がOpenADC()関数の引数でおこなわれます。


 <試作品仕様>
  ・ PIC18F4550のAN0端子から内臓AD変換器をつかい電圧を読み込む
  ・ リファレンス電圧は+5V(PICの電源電圧)とする。
  ・ 液晶には以下を200msec毎に表示する。
     @ 1行目 …… AD変換値
     A 2行目 …… 入力電圧(単位:ボルト)


 <試作品回路図>
  PIC18F4550の場合の回路図を以下にしめします。(→回路図のPDFファイル

 <試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています


   <プログラム例>
/*
  C18コンパイラ
     PIC18F4550 内臓AD変換回路読込み
*/

#include <p18f4550.h>
#include <adc.h>
#include <delays.h>
#include <stdio.h>
#include <stdlib.h>

#include "1lcd_lib_C18.h"
#include "1lcd_lib_C18.c"

#pragma config PLLDIV = 5       //96MHz PLL Prescalar(1、2、3、4、5、6、10、12のみ) : 外部周波数÷4MHz
                                                        //20MHz ÷ 5 = 4MHz → 96MHz(=4MHz×24 :固定)
#pragma config USBDIV = 2       // Full Speed USB Clock Source Selection : 2(constant)
#pragma config CPUDIV = OSC1_PLL2       //CPU System Clock Postscaler 
                                                                        // PICのシステムクロック周波数:48MHz(=96MHz ÷2)
#pragma config FOSC = HS // システムクロック=20MHz 
//#pragma config FOSC = HSPLL_HS        // システムクロック=48MHz


#pragma config WDT = OFF
#pragma config LVP = OFF



void lcd_printf(char* str)      //液晶表示補助関数
{
        while(*str)     //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;
        }       
}



void Ad_Func()  //AD変換読込み & 表示
{
        int ADread;
        char str[17];
        char str2[30];
        float Vin,Vin1000;
        long int Vin1000i;
        int Vi,Vf;

        

//      SetChanADC(ADC_CH1);    //チャンネルを切り替える場合
        ConvertADC();
        while( BusyADC());      //AD変換が終わるまで待つ
        ADread = ReadADC();     //AD変換値読込み
                                                
                                //液晶へ表示
        lcd_clear();
        sprintf(str,"ADread=%d",ADread);
        lcd_printf(&str[0]);//  AD変換読込み値を液晶に1行目に表示    読込み値:1023(at 5V)

        Vin = (float)ADread/1023*5;
        Vi = (int)Vin;
        Vf =(int)( (Vin - (int)Vin)*100);

        sprintf(&str2[0],"Vin[v]=%d.%d",Vi,Vf); // %f(浮動少数)は未サポート
        lcd_cmd(0xC0);//2行目の先頭へ
        lcd_printf(&str2[0]);// AD変換読込み値を液晶に2行目に表示    読込み値:1023(at 5V)  
        
        Delay10KTCYx(100);      //200msec 毎に読込み 
                                                // 10KT:0.05μsec×4×10000=2000μsec=2msec
}



void main (void)
{
        char tempBuf[17];       //液晶表示データの一時保存レジスタ

        OpenADC(ADC_FOSC_64 &           //AD変換用クロック  システムクロックの1/64 0.05μsec×64=3.2μsec >= 1.6μsec → OK
                        ADC_RIGHT_JUST &        //変換結果の保存方法 左詰め 
                        ADC_8_TAD,              //AD変換のアクイジションタイム選択 3.2μsec(=1Tad)×8Tad=25.6μsec >= 12.8μsec → OK
                        ADC_CH0 &                       //AD変換するのチャンネル選択(PIC18Fは同時に複数のAD変換はできない)
                        ADC_INT_OFF &           //AD変換での割込み使用の有無
                        ADC_VREFPLUS_VDD &      //Vref+の設定   PICの電源電圧と同じ:ADC_VREFPLUS_VDD  or 外部(AN3)の電圧:ADC_VREFPLUS_EXT
                        ADC_VREFMINUS_VSS,      //Vref-の設定   PICの0V:ADC_VREFMINUS_VSS    or 外部(AN2)の電圧:ADC_VREFMINUS_EXT
                        0b1110  //ポートのアナログ・デジタル選択 (ADCON1の下位4ビットを記載)  AN0のみアナログポートを選択、他はデジタルポートを選択
                                        //例  アナログポートが AN0のみ → 0b1110  、AN0 & AN1 → 0b1011、 AN0 & AN1 & AN2 →1100 他 詳細データシート参照
                        );


        Delay10KTCYx(25);//50msec液晶立ち上がりを待つ  10KT:0.05μsec×4×10000=2000μsec=2msec
        lcd_init();                                     // LCD初期化
        lcd_cmd(0b00001100);        // カーソル:OFF    ブリンク:OFF
        lcd_clear();
        sprintf(&tempBuf[0],"AD Converter !!"); //文字列としてバッファーに収納
        lcd_printf(&tempBuf[0]);

        lcd_cmd(0xC0);//2行目の先頭へ
        sprintf(&tempBuf[0],"     Start2 !!");  //文字列としてバッファーに収納
        lcd_printf(&tempBuf[0]);

        while (1)
    {
                Ad_Func();
    }
        CloseADC();

}


//*************************************************************************
//インクルードファイル    1lcd_lib_C18.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ
//1lcd_lib.cをC18コンパイラ用に変更したものです。
//*************************************************************************
#define         lcd_port                LATD    //DataOutPort    pin : 上位4bit
#define         lcd_stb                 LATDbits.LATD0  //stb OutPort  
#define         lcd_rs                  LATDbits.LATD2  // rs OutPort
#define         port_Mode               TRISD   // Port Mode set                        


void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_out(char code, char flag);



//**************************************************************************
//インクルードファイル    1lcd_lib_C18.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ
//1lcd_lib.cをC18コンパイラ用に変更したものです。
//**************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C18コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//////////////////////////////////////////////

#include        "delays.h"
#include        "1lcd_lib_C18.h"


//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        port_Mode = 0;  // PIC側の DataPort、stbPort、 rsPort を出力モードに設定
        lcd_port = code & 0xF0;
        if (flag == 0)
                lcd_rs = 1;                     //表示データの場合
        else
                lcd_rs = 0;                     //コマンドデータの場合
        
        Delay10TCYx(1);                 //10NOP 
        lcd_stb = 1;                    //strobe out
        Delay10TCYx(1);                 //10NOP
        lcd_stb = 0;                    //reset strobe
}


//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);                       //上位4ビット出力
        lcd_out(asci<<4, 0);            //下位4ビット出力
        Delay10TCYx(50);                        //500NOP (50μsec待ち at 40MHz)
}


/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                //上位4ビット出力
        lcd_out(cmd<<4, 1);             //下位4ビット出力
        if((cmd & 0x03) != 0)
                Delay10KTCYx(2);                //2msec待ち at 40MHz
        else
                Delay10TCYx(50);                //50usec待ち at 40MHz
}


/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  //初期化コマンド出力
//      Delay10KTCYx(15);           //15msec待ち at 40MHz
}


/////// 初期化関数
void lcd_init(void)
{
        lcd_out(0x30, 1);               //8bit mode set
        Delay10KTCYx(5);                //5msec待ち at 40MHz
        lcd_out(0x30, 1);               //8bit mode set
        Delay10KTCYx(1);                //1msec待ち at 40MHz
        lcd_out(0x30, 1);               //8bit mode set
        Delay10KTCYx(1);                //1msec待ち at 40MHz
        lcd_out(0x20, 1);               //4bit mode set
        Delay10KTCYx(1);                //1msec待ち at 40MHz
        lcd_cmd(0x2E);                  //DL=0 4bit mode
        lcd_cmd(0x08);                  //display off C=D=B=0
        lcd_cmd(0x0D);                  //display on C=D=1 B=0
        lcd_cmd(0x06);                  //entry I/D=1 S=0
        lcd_cmd(0x01);                  //all clear
}


 

<動作結果>
 AN0端子の入力電圧(デジタルテスタ表示値)が 概略 0v、 2.5v、 5.0vの時の液晶表示を以下に示します。

AN0端子入力電圧
0v 2.5v 5.0v




 (2)入力電圧を液晶に表示(PIC18F452)
  PIC18F452の内臓ADコンバータからAD変換値を読込み、値を液晶に表示した例を紹介します。 PICの種類によって
 OpenADC()関数の引数、及び引数の数が異なります。PIC18F452の場合は一部の設定がOpenADC()関数の引数では
 設定されない為、レジスタに直接書き込む必要があります。具体的には、端子の属性(アナログポート、デジタルポート、
 +Vref、 -Vref )を設定するためにADCON2レジスタの下位4ビットに直接書き込みます。
 


 <試作品仕様>
  ・ PIC18F452のAN0端子から内臓AD変換器をつかい電圧を読み込む
  ・ リファレンス電圧は+5V(PICの電源電圧)とする。
  ・ 液晶には以下を200msec毎に表示する。
     @ 1行目 …… AD変換値
     A 2行目 …… 入力電圧(単位:ボルト)

 <試作品回路図>PIC18F452をつかった場合の回路図を以下に示します。(→回路図のPDFファイル




 <試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています

   <プログラム例>

/*
  C18コンパイラ
     PIC18F452 内臓AD変換回路読込み
*/

#include <p18f452.h>
#include <adc.h>
#include <delays.h>
#include <stdio.h>
#include <stdlib.h>

#include "1lcd_lib_C18.h"
#include "1lcd_lib_C18.c"


#pragma config OSC = HSPLL      // f = 40MHz ( = 10MHz × 4(PLL))
#pragma config WDT = OFF
#pragma config LVP = OFF




void lcd_printf(char* str)      //液晶表示補助関数
{
        while(*str)     //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;
        }       
}



void Ad_Func()  //AD変換読込み & 表示
{
        int ADread;
        char str[17];
        char str2[30];
        float Vin,Vin1000;
        long int Vin1000i;
        int Vi,Vf;

        

//      SetChanADC(ADC_CH1);    //チャンネルを切り替える場合
        ConvertADC();
        while( BusyADC());      //AD変換が終わるまで待つ
        ADread = ReadADC();     //AD変換値読込み
                                                
                                //液晶へ表示
        lcd_clear();
        sprintf(str,"ADread=%d",ADread);
        lcd_printf(&str[0]);//  AD変換読込み値を液晶に1行目に表示    読込み値:1023(at 5V)

        Vin = (float)ADread/1023*5;
        Vi = (int)Vin;
        Vf =(int)( (Vin - (int)Vin)*100);

        sprintf(&str2[0],"Vin[v]=%d.%d",Vi,Vf); // %f(浮動少数)は未サポート
        lcd_cmd(0xC0);//2行目の先頭へ
        lcd_printf(&str2[0]);// AD変換読込み値を液晶に2行目に表示    読込み値:1023(at 5V)  
        
        Delay10KTCYx(100);      //200msec 毎に読込み 
                                                // 10KT:0.05μsec×4×10000=2000μsec=2msec
}



void main (void)
{
        char tempBuf[17];       //液晶表示データの一時保存レジスタ

        OpenADC(ADC_FOSC_64 &           //AD変換用クロック  システムクロックの1/64 0.05μsec×64=3.2μsec >= 1.6μsec → OK
                        ADC_RIGHT_JUST &        //変換結果の保存方法 左詰め 
                        ADC_1ANA_0REF,          //AD変換のアクイジションタイム選択 3.2μsec(=1Tad)×8Tad=25.6μsec >= 12.8μsec → OK
                        ADC_CH0 &                       //AD変換するのチャンネル選択(PIC18Fは同時に複数のAD変換はできない)
                        ADC_INT_OFF                     //AD変換での割込み使用の有無
                        );
        ADCON1 = (ADCON1 & 0xF0) | 0b00001110;  //0b1110 → アナログ端子RA0のみ +Vref=Vdd -Vrerf=GND
                                                                //  ADCON1の下位4ビットで端子の属性を指定する → アナログ端子、デジタル端子、+Vref端子、-Vref端子
                                                                //例    0b1111 → RA0のみアナログ端子、+Vref端子=RA3、-Vref=RA2
                                                                //      0b0100 → RA0、RA1,RA3アナログ端子  +Vref=Vdd -Vrerf=GND  他 詳細18F452のデータシート参照 


        Delay10KTCYx(25);//50msec液晶立ち上がりを待つ  10KT:0.05μsec×4×10000=2000μsec=2msec
        lcd_init();                                     // LCD初期化
        lcd_cmd(0b00001100);        // カーソル:OFF    ブリンク:OFF
        lcd_clear();
        sprintf(&tempBuf[0],"AD Converter !!"); //文字列としてバッファーに収納
        lcd_printf(&tempBuf[0]);

        lcd_cmd(0xC0);//2行目の先頭へ
        sprintf(&tempBuf[0],"     Start2 !!");  //文字列としてバッファーに収納
        lcd_printf(&tempBuf[0]);

        while (1)
    {
                Ad_Func();
    }
        CloseADC();

}



//*************************************************************************
//インクルードファイル    1lcd_lib_C18.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ
//1lcd_lib.cをC18コンパイラ用に変更したものです。
//*************************************************************************
#define         lcd_port                LATD    //DataOutPort    pin : 上位4bit
#define         lcd_stb                 LATDbits.LATD0  //stb OutPort  
#define         lcd_rs                  LATDbits.LATD2  // rs OutPort
#define         port_Mode               TRISD   // Port Mode set                        


void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_out(char code, char flag);



//**************************************************************************
//インクルードファイル    1lcd_lib_C18.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ
//1lcd_lib.cをC18コンパイラ用に変更したものです。
//**************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C18コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//////////////////////////////////////////////

#include        "delays.h"
#include        "1lcd_lib_C18.h"


//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        port_Mode = 0;  // PIC側の DataPort、stbPort、 rsPort を出力モードに設定
        lcd_port = code & 0xF0;
        if (flag == 0)
                lcd_rs = 1;                     //表示データの場合
        else
                lcd_rs = 0;                     //コマンドデータの場合
        
        Delay10TCYx(1);                 //10NOP 
        lcd_stb = 1;                    //strobe out
        Delay10TCYx(1);                 //10NOP
        lcd_stb = 0;                    //reset strobe
}


//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);                       //上位4ビット出力
        lcd_out(asci<<4, 0);            //下位4ビット出力
        Delay10TCYx(50);                        //500NOP (50μsec待ち at 40MHz)
}


/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                //上位4ビット出力
        lcd_out(cmd<<4, 1);             //下位4ビット出力
        if((cmd & 0x03) != 0)
                Delay10KTCYx(2);                //2msec待ち at 40MHz
        else
                Delay10TCYx(50);                //50usec待ち at 40MHz
}


/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  //初期化コマンド出力
//      Delay10KTCYx(15);           //15msec待ち at 40MHz
}


/////// 初期化関数
void lcd_init(void)
{
        lcd_out(0x30, 1);               //8bit mode set
        Delay10KTCYx(5);                //5msec待ち at 40MHz
        lcd_out(0x30, 1);               //8bit mode set
        Delay10KTCYx(1);                //1msec待ち at 40MHz
        lcd_out(0x30, 1);               //8bit mode set
        Delay10KTCYx(1);                //1msec待ち at 40MHz
        lcd_out(0x20, 1);               //4bit mode set
        Delay10KTCYx(1);                //1msec待ち at 40MHz
        lcd_cmd(0x2E);                  //DL=0 4bit mode
        lcd_cmd(0x08);                  //display off C=D=B=0
        lcd_cmd(0x0D);                  //display on C=D=1 B=0
        lcd_cmd(0x06);                  //entry I/D=1 S=0
        lcd_cmd(0x01);                  //all clear
}


 

 <動作結果>
  入力電圧が2.5vの場合の写真を以下に示します。




(3)入力電圧を液晶に表示(PIC18F87K90)


<試作品回路図>PIC18F87K90をつかった場合の回路図を以下に示します。(→回路図のPDFファイル


<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています



          

   <プログラム例>

/*
AD コンバータ 12ビットAD 
                                                                                        PC18F87K90              
*/

#include <p18f87K90.h>

#include <stdio.h>
#include <delays.h>
#include <timers.h>
#include <adc.h>

#include "1lcd_lib_C18.h"
#include "1lcd_lib_C18.c"


#pragma config FOSC = XT                //FOSC = HS // システムクロック=1MHz 
#pragma config XINST = OFF
#pragma config  WDTEN = OFF     //ウォッドックタイマ OFF



unsigned int Count_10msec;

        char tempBuf[17];       //液晶表示データの一時保存レジスタ

    long int ADread;
        char str[17];
        char str2[30];
        float Vin,Vin1000;
        long int Vin1000i;
        int Vi,Vf;




void delay_ms (long int cycle)  // CCSコンパイラと同じ delay_ms(long int) 関数を設計
{
        long int i = 0;
        for (i = 0; i < cycle; i++)Delay10TCYx(25);      //  25 x 40μsec = 1000μsec // Delay10TCY():40μsec  
}



void lcd_printf(char* str)      //液晶表示補助関数
{
        while(*str)     //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;
        }       
}




void Ad_Func()  //AD変換読込み & 表示
{
    
        
                SetChanADC(ADC_CH0);    //チャンネルを切り替える場合
        ConvertADC();
        while( BusyADC());      //AD変換が終わるまで待つ
        ADread = ReadADC();     //AD変換値読込み
                                                
                                //液晶へ表示
        lcd_clear();
        sprintf(str,"ADread=%ld",ADread);
        lcd_printf(&str[0]);//  AD変換読込み値を液晶に1行目に表示    読込み値:1023(at 5V)

        Vin = (float)ADread/4095*3.3;
        Vi = (int)Vin;
        Vf =(int)( (Vin - (int)Vin)*100);

        sprintf(&str2[0],"Vin[v]=%d.%d",Vi,Vf); // %f(浮動少数)は未サポート
        lcd_cmd(0xC0);//2行目の先頭へ
        lcd_printf(&str2[0]);// AD変換読込み値を液晶に2行目に表示    読込み値:1023(at 5V)  
        
      
}


#pragma interrupt my_Func               // 10msec タイマ1 インターバル割り込み
#pragma code isrcode = 0x08
void isr_direct(void)
{ _asm goto my_Func _endasm }
#pragma code
void my_Func(void)
{
        
        LATJbits.LATJ0 = 0;
        
        PIR1bits.TMR1IF = 0;    // タイマ1割り込みフラグをクリアする
        WriteTimer1(15536);     // 1μsec × 4 × 1 × 50000 = 200000μsec = 200msec (at システムクロック1MHz)
                                                        // 256×256 - 50000 = 15536
        Ad_Func();

        LATJbits.LATJ0 = 1;
}



void main (void)
{
        unsigned char channel=0x00,config1=0x00,config2=0x00,config3=0x00,portconfig=0x00;


        TRISD = 0;
        TRISJ = 0;

        TRISAbits.TRISA0 = 1;
        TRISAbits.TRISA3 = 1;

        ANCON0 = 0b00001001;    //RA0
        ANCON1 = 0;
        ANCON2 = 0;


    config1 =                                   //ADCON0: A/D CONTROL REGISTER 0
                        ADC_CH0 |                       //AD変換するのチャンネル選択(PIC18Fは同時に複数のAD変換はできない)                
                        ADC_INT_OFF |           //AD変換での割込み使用の有無 
                        ADC_REF_VDD_VDD |       //Vref+の設定   PICのVcc 
                        ADC_REF_VDD_VSS ;       //Vref-の設定   PICの0V 

                                                                //ADCON1: A/D CONTROL REGISTER 1

        config2 =                                       //ADCON2: A/D CONTROL REGISTER 2
                        ADC_FOSC_2 |            //AD変換用クロック  システムクロックの1/2 
                        ADC_RIGHT_JUST |        //変換結果の保存方法 左詰め 
                        ADC_2_TAD ;                     //AD変換のアクイジションタイム選択 変換クロック時間(=1Tad)×2Tad

        OpenADC(config1,config2,portconfig);




        lcd_init();                                     // LCD初期化
        lcd_cmd(0b00001100);        // カーソル:OFF    ブリンク:OFF
        lcd_clear();
        sprintf(&tempBuf[0],"AD Converter !!"); //文字列としてバッファーに収納
        lcd_printf(&tempBuf[0]);

        lcd_cmd(0xC0);//2行目の先頭へ
        sprintf(&tempBuf[0],"     Start2 !!");  //文字列としてバッファーに収納
        lcd_printf(&tempBuf[0]);



         while (1)
    {
                Ad_Func();
                delay_ms(200);
    }


}




//************************************************
//インクルードファイル    1lcd_lib_C18.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリを
//C18コンパイラ用に変更したものです。
//************************************************
#define         lcd_port                LATD    //DataOutPort    pin : 上位4bit
#define         lcd_stb                 LATDbits.LATD3  //stb OutPort  
#define         lcd_rs                  LATDbits.LATD2  // rs OutPort
#define         port_Mode               TRISD   // Port Mode set                        


void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_out(char code, char flag);





//***********************************************
//インクルードファイル    1lcd_lib_C18.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリを
//C18コンパイラ用に変更したものです。
//***********************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C18コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//////////////////////////////////////////////

#include        "delays.h"
#include        "1lcd_lib_C18.h"


//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        port_Mode = 0;  // PIC側の DataPort、stbPort、 rsPort を出力モードに設定
        lcd_port = code & 0xF0;
        if (flag == 0)
                lcd_rs = 1;                     //表示データの場合
        else
                lcd_rs = 0;                     //コマンドデータの場合
        
        Delay10TCYx(1);                 //10NOP 
        lcd_stb = 1;                    //strobe out
        Delay10TCYx(1);                 //10NOP
        lcd_stb = 0;                    //reset strobe
}


//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);                       //上位4ビット出力
        lcd_out(asci<<4, 0);            //下位4ビット出力
        Delay10TCYx(50);                        //500NOP (50μsec待ち at 40MHz)
}


/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                //上位4ビット出力
        lcd_out(cmd<<4, 1);             //下位4ビット出力
        if((cmd & 0x03) != 0)
                Delay10KTCYx(2);                //2msec待ち at 40MHz
        else
                Delay10TCYx(50);                //50usec待ち at 40MHz
}


/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  //初期化コマンド出力
//  Delay10KTCYx(15);           //15msec待ち at 40MHz
}


/////// 初期化関数
void lcd_init(void)
{
        lcd_out(0x30, 1);               //8bit mode set
        Delay10KTCYx(5);                //5msec待ち at 40MHz
        lcd_out(0x30, 1);               //8bit mode set
        Delay10KTCYx(1);                //1msec待ち at 40MHz
        lcd_out(0x30, 1);               //8bit mode set
        Delay10KTCYx(1);                //1msec待ち at 40MHz
        lcd_out(0x20, 1);               //4bit mode set
        Delay10KTCYx(1);                //1msec待ち at 40MHz
        lcd_cmd(0x2E);                  //DL=0 4bit mode
        lcd_cmd(0x08);                  //display off C=D=B=0
        lcd_cmd(0x0D);                  //display on C=D=1 B=0
        lcd_cmd(0x06);                  //entry I/D=1 S=0
        lcd_cmd(0x01);                  //all clear
}



 



■ XC8 コンパイラ編 

<試作品回路図>  PIC18F14K50をつかった場合の回路図を以下に示します。(→回路図のPDFファイル




<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています





          

   <プログラム例>

//AD コンバータ 
//             チャンネルAN8(RC6)

#include <p18f14K50.h>
#include <xc.h>

#include    <stdio.h>
#include    <stdarg.h>

#include "lcd_lib_XC8.h"

#define _XTAL_FREQ  48000000        //PLL ON  Periferal= 12MHz x 4 = 48MHz

#pragma config CPUDIV = NOCLKDIV ,USBDIV = OFF,PCLKEN = ON
#pragma config FOSC = HS,PLLEN = ON, HFOFST = OFF           //PLL ON  Periferal= 12MHz x 4 = 48MHz
#pragma config PWRTEN = ON, BOREN = OFF, MCLRE = OFF, BORV = 30
#pragma config WDTEN = OFF,LVP = OFF,FCMEN = OFF, IESO = OFF
#pragma config CP0 = OFF,XINST = OFF
#pragma config STVREN = OFF, BBSIZ = OFF,CPB = OFF,CP1 = OFF,CPD = OFF  //省略するとwarnig がでる
#pragma config WRT0 = OFF,WRT1 = OFF,WRTC = OFF,WRTB = OFF,EBTR0 = OFF,EBTR1 = OFF,EBTRB = OFF //省略するとwarnig がでる


char Buf[17];   //液晶表示データの一時保存レジスタ
int Mode = 0;

int ADread;
float Vin,Vin1000;
long int Vin1000i;
int Vi,Vf;

void delay_ms(unsigned short msec)        //1msec遅延関数
{
        unsigned short i;

        for(i=0; i<msec; i++)
        __delay_ms(1);  // __delay_ms(n); //n = 1?16
 //     __delay_us(1);  //__delay_us(n); //n = 1?16426    //1μsec遅延関数

}

void lcd_printf(char* str)      //液晶表示補助関数
{
        while(*str)     //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;
        }
}

void AdFunc(void)
{
     char* pStr;

        ADCON0 = 0b00100001;   //AN8(RC6)選択、ADコンバータ有効化
        ADCON0bits.GO = 1;              // AD変換開始
        while (ADCON0bits.GO);          // AD変換完了待ち
        ADread = ADRESL+(ADRESH*256);   // 10bitの値に変換

                                //液晶へ表示
        lcd_clear();
        pStr = &Buf[0];
        sprintf(pStr,"ADread=%d",ADread);
        lcd_printf(pStr);//  AD変換読込み値を液晶に1行目に表示    読込み値:1023(at 5V)

        Vin = (float)ADread/1023*5;
        Vi = (int)Vin;
        Vf =(int)( (Vin - (int)Vin)*100);

        sprintf(pStr,"Vin[v]=%d.%d",Vi,Vf); // %f(浮動少数)は未サポート
        lcd_cmd(0xC0);//2行目の先頭へ
        lcd_printf(pStr);// AD変換読込み値を液晶に2行目に表示    読込み値:1023(at 5V)

}



int main()
{
    char* pStr;

    ANSEL = 0x00;                                       // デジタルに設定
    ANSEL = 0x00;                                       // デジタルに設定
    ANSELH =0b00000011;     // RC6(AN8),RC7(AM9)のみアナログ

  // ADC初期化
  //  ADCON0 = 0;                       // 停止
    ADCON0bits.ADON = 0;                //ADC: Disable

//  ADCON1 = 0;                                         // VDD-Vss
    ADCON1bits.PVCFG0 = 0;      // Vref+ = Vdd  //Positive Voltage Reference select bit
    ADCON1bits.PVCFG1 = 0;      //
    ADCON1bits.NVCFG0 = 0;      //Vref- = GND   //Negative Voltage Reference select bit
    ADCON1bits.NVCFG1 = 0;


 //   ADCON2 = 0xBE;                                    // 右詰め,20Tad,Fosc/64
    
    ADCON2bits.ADFM = 1;     //右詰め
    ADCON2bits.ADCS0 = 0;   //110: FOSC/64  //AD変換用クロック選択  //A/D Conversion Clock Select bits
    ADCON2bits.ADCS1 = 1;   
    ADCON2bits.ADCS2 = 1;
    
    ADCON2bits.ACQT0 = 1;    //20TAD;   //TAD(AD変換用クロック周期)×20 //アクイジションタイム(充電時間)
                            ///A/D Acquisition time select bits. Acquisition time is the duration that the A/D charge
    ADCON2bits.ACQT1 = 1;    //holding capacitor remains connected to A/D channel from the instant the GO/DONE bit is
    ADCON2bits.ACQT2 = 1;    //set until conversions begins.

    TRISC = 0b11000000;
    TRISB = 0;

    lcd_init();                                 // LCD初期化
    lcd_cmd(0b00001100);        // カーソル:OFF    ブリンク:OFF
    lcd_clear();
    pStr = &Buf[0];

    lcd_cmd(0x80);      //1行目の先頭へ
    sprintf(pStr,"XC8");        //文字列としてバッファーに収納
    lcd_printf(pStr);

    lcd_cmd(0xC0);//2行目の先頭へ
    sprintf(pStr,"  A/D  Start !!");    //文字列としてバッファーに収納
    lcd_printf(pStr);

    delay_ms(2000);

    while(1)
    {
        AdFunc();
        delay_ms(500);
    }
    return 0;
}

//************************************************
//インクルードファイル    lcd_lib_XC8.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリを
//XC8コンパイラ用に変更したものです。
//************************************************

// LCDポート設定
#define lcd_port_DB7    LATBbits.LATB7  //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6    LATBbits.LATB6  //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5    LATBbits.LATB5  //LCDのDB5 (12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4    LATBbits.LATB4  //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_stb         LATCbits.LATC5  //stb OutPort
#define lcd_rs          LATCbits.LATC4  // rs OutPort


void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_out(char code, char flag);



//***********************************************
//インクルードファイル    lcd_lib_XC8.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリを
//XC8コンパイラ用に変更したものです。
//***********************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C18コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//////////////////////////////////////////////

#include    "lcd_lib_XC8.h"
#include    <p18f14K50.h>
#include <stdio.h>
#include <stdlib.h>

#define _XTAL_FREQ  48000000

//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        //port_Mode = 0;        // PIC側の DataPort、stbPort、 rsPort を出力モードに設定

        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;



        //lcd_port = code & 0xF0;

        if (flag == 0)
                lcd_rs = 1;                     //表示データの場合
        else
                lcd_rs = 0;                     //コマンドデータの場合


        _delay(10);     //Delay10TCYx(1);                       //10NOP

        lcd_stb = 1;                    //strobe out
        _delay(10);     //Delay10TCYx(1);                       //10NOP
        lcd_stb = 0;                    //reset strobe
}


//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);                       //上位4ビット出力
        lcd_out(asci<<4, 0);            //下位4ビット出力
        _delay(500);    //Delay10TCYx(50);                      //500NOP (50μsec待ち at 40MHz)
}


/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                //上位4ビット出力
        lcd_out(cmd<<4, 1);             //下位4ビット出力
        if((cmd & 0x03) != 0)
                __delay_ms(2);    //Delay10KTCYx(2);            //2msec待ち at 40MHz
        else
                __delay_us(50); //Delay10TCYx(50);              //50usec待ち at 40MHz
}


/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  //初期化コマンド出力
//  Delay10KTCYx(15);           //15msec待ち at 40MHz
}


/////// 初期化関数
void lcd_init(void)
{
        lcd_out(0x30, 1);               //8bit mode set
        __delay_ms(5);    //Delay10KTCYx(5);            //5msec待ち at 40MHz
        lcd_out(0x30, 1);               //8bit mode set
        __delay_ms(1);    //Delay10KTCYx(1);            //1msec待ち at 40MHz
        lcd_out(0x30, 1);               //8bit mode set
        __delay_ms(1);    //Delay10KTCYx(1);            //1msec待ち at 40MHz
        lcd_out(0x20, 1);               //4bit mode set
        __delay_ms(1);    //Delay10KTCYx(1);            //1msec待ち at 40MHz
        lcd_cmd(0x2E);                  //DL=0 4bit mode
        lcd_cmd(0x08);                  //display off C=D=B=0
        lcd_cmd(0x0D);                  //display on C=D=1 B=0
        lcd_cmd(0x06);                  //entry I/D=1 S=0
        lcd_cmd(0x01);                  //all clear
}







 <動作結果>

入力電圧 液晶表示
0V
2.5V
5.0V




■ C30コンパイラ dsPIC編

  C30コンパイラの場合、内臓ADコンバータからの12bitAD変換値読込みの基本的な流れは以下のようになります。

    @ OpenADC12() 関数で SFRの設定をおこなう。
    A SetChanADC12()関数で 読み込みのチャンネルを選択する。
    B ConvertADC12()関数で 読み込みを開始する。 (注1)( ADCON1bits.SAMP =1; )
    C BusyADC12()関数で AD変換が完了するのを待つ (注1)( while(!ADCON1bits.DONE); )
    D ReadADC12()関数で AD変換値を読み込む (注1)(AdcValue = ADCBUF0;)
    E CloseADC12()関数で AD変換をDisableにする
      (注1)( )内のように直接レジスタにアクセスした方が速いようです。
            (注2)10ビット用の関数は関数の末尾12が10となります。
 


(1)入力電圧を液晶に表示(dsPIC30F2012)
  dsPIC30F2012の内臓ADコンバータからAD変換値を読込み、値を液晶に表示した例を紹介します。書き込みはICSPを
 使っています。

 <試作品仕様>
  ・ dsPIC30F2012のAN3端子から内臓AD変換器をつかい電圧を読み込む
  ・ リファレンス電圧は+5V(PICの電源電圧)とする。
  ・ 液晶には以下を200msec毎に表示する。
     @ 1行目 …… AD変換値
     A 2行目 …… 入力電圧(単位:ボルト)


 <試作品回路図>
  dsPIC30F2012の場合の回路図を以下にしめします。(→回路図のPDFファイル


<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています


   <プログラム例>
///************************************************************/
//*  AD変換 液晶表示
//*      dsPIC30F2012   
//************************************************************/

// MPLAB プロジェクトへの追加ファイル
// Linker Scriptフォルダ  p30f2012.gld
// Library Filesフォルダ  lib30F2012-coff.a

#include        "p30f2012.h"
#include        <stdio.h>
#include        <adc12.h>
#include    <timer.h>

#include        "1lcd_lib_C30.h"



_FOSC(CSW_FSCM_OFF &                   // クロック切り替えなし、フェールセイフクロックモニタなし
                FRC_PLL16              //内臓高速RC発振器(7.37MHz)、PLL:16倍 → システムクロック周波数=7.37×16=117.92MHz
                );
_FWDT(WDT_OFF); 

_FBORPOR(PBOR_ON &                      //ブラウンアウトリセット機能:ON
                BORV_42 &               //ブラウンアウト電圧:4.2V
                PWRT_64 &               //パワーオンリセットタイマ64msec
                MCLR_EN                 //MCLR機能:ON
                );
_FGS(CODE_PROT_OFF);                    //コードプロテクト:OFF

unsigned int Config1 =                  //ADCON1レジスタの設定
        ADC_MODULE_ON &                 //ADON bit15=1 : ADコンバータモジュール → ON  //AD Module On/Off
        ADC_IDLE_CONTINUE &             //ADSIL bit13=0 : アイドル時の動作 → 動作継続 //Idle Mode Operation
        ADC_FORMAT_INTG &               //FORM bit9-8=00 :出力データのフォーマット → 整数 //Result Output Format
        ADC_CLK_AUTO &                  //SSRC bit5-7=111 :変換開始トリガ設定  //Conversion Trigger Source
                                        //       →ADCON3のSAMCによるクロック(サンプルホールド)が終了後変換自動開始
        ADC_AUTO_SAMPLING_OFF &         //ASAM bit2=1 : ADサンプリング自動開始→手動開始 //Auto Sampling Select
        ADC_SAMP_OFF;                   //SAMP bit1=0 : サンプリング手動制御→OFF //Sample Enable
                                        //  (例)ASAM = 0(ADC_AUTO_SAMPLING_OFF) の時 SAMP=1(ADC_SAMP_ON)で変換開始
                                        //DONE bit0     : AD変換終了フラグ(AD変換が終了すると1が立つ、 書き込み不可)


unsigned int Config2 =                  //ADCON2レジスタの設定
        ADC_VREF_AVDD_AVSS &            //VCFG bit13-15=000: S/Hアンプのリファレンス設定: 基準電圧Vdd、シングルエンド //Voltage Reference
        ADC_SCAN_OFF &                  //CSCNA bit10=0 : MUX交互自動スキャン制御→オフ //Scan Section
        ADC_SAMPLES_PER_INT_1 &         //SMPI bit2-5 : 割込み頻度→1回毎 //Number of Samples between Interrupts
        ADC_ALT_BUF_OFF &               //BUFM bit1=0: 交互バッファー制御→なし //Buffer mode Select
        ADC_ALT_INPUT_OFF;              //ALTS bit0=0: AD入力の複数バッファーへの格納//Alternate Input sample Mode Select(



unsigned int Config3 =                  //ADCON3レジスタの設定
        ADC_SAMPLE_TIME_10 &            //SAMC bit8-12 :サンプルホールド時間 → 10サイクル(TAD)//Auto Sample Time bits

        ADC_CONV_CLK_SYSTEM &           //ADRC bit7=0 :AD変換クロック→システムクロック //Conversion Clock Source Select

        ADC_CONV_CLK_32Tcy;             //ADCS bit0-5 :変換クロック数→32Tcy(設定のMAXを選択) //Conversion Clock Select




unsigned int ConfigPort =               //ADPCFGレジスタの設定 ANLOG/DIGITAl Pin Select
                                                        //ex1.  ENABLE_ALL_ANA   ex2. ENABLE_ALL_DIG   ex3. ENABLE_AN0_ANA & ENABLE_AN1_ANA
        ENABLE_AN3_ANA;                 //AN1 → アナログポート

unsigned int ConfigScan =               //ADCSSLレジスタの設定         Scan Channel Select
        SCAN_NONE;                      //ADCSLL = 0x0000 : 自動スキャン→スキャンせず


unsigned int Channel1 =                 //ADCHSレジスタの設定
        ADC_CH0_POS_SAMPLEA_AN3 &       //マルチプレクサA(S/Hアンプ)のVref+への接続チャンネル → チャンネル1
        ADC_CH0_NEG_SAMPLEA_NVREF;      //マルチプレクサA(S/Hアンプ)のVref-への接続チャンネル → Vss


void AdcFunc(void);
void delay_ms(unsigned int);

unsigned int Count=0;
unsigned int AdcValue;
char Buf[17];                            //文字列のバッファー用レジスタ


void delay_ms(unsigned int N)            //ウェイト関数
{
        __delay32(Clock/4000*N);
}

void AdcFunc(void)                        // AD変換読み取り & 液晶表示
{
        float Volt;
        unsigned int    I;      
        unsigned int    F;
        
                SetChanADC12(Channel1);   //Vref-(RB1、AN1) → GND
                ADCON1bits.SAMP =1;       //サンプリング開始
                                          //サンプルホールド時間:8TAD (ADCON3のSAMC<3:0>)
                                          //変換の自動開始                                                                               //変換時間:31TAD (ADCON3のADCS<5:0>)
        //      while(BusyADC12());
                while(!ADCON1bits.DONE);  //AD変換終了フラグが1になるまでまつ


//              AdcValue = ReadADC12(0);  //AD変換値読込み(読込みが遅い) 
                AdcValue = ADCBUF0;       //AD変換値読込み(レジスタ直読 → 読込みが早い) 

                Count++;
                lcd_clear();                             //全消去
                sprintf(Buf,"AdV=%u",AdcValue);          //バッファーに文字列をセット
                lcd_str(Buf);                            // 開始メッセージ1行目表示
        
                Volt =(float)AdcValue/4095*5;
                I = (unsigned int) Volt;
                F = (unsigned int)(( Volt - I)*1000);                   
                lcd_cmd(0xC0);                            //2行目の先頭へ
                sprintf(Buf,"Volt=%u.%u[V]",I,F);         //文字列としてバッファーに収納
                lcd_str(Buf);                             // 開始メッセージ1行目表示
}


void _ISR _T1Interrupt(void)                               //タイマ1割込み
{
        IFS0bits.T1IF = 0;                                 //フラグクリア
        AdcFunc();                                         // AD変換読み取り & 液晶表示                                              
}


/// メイン関数
int     main(void) {

        TRISB = 0b0000000000001000;                        // AD入力のbit3(AN3 RB3)のみ入力
        TRISF = 0;



        // A/D変換モジュールのオフを確認します
        ADCON1bits.ADON=0;
        ConfigIntADC12(ADC_INT_DISABLE);                        
        OpenADC12(
                                Config1,                //ADCON1レジスタの設定
                                Config2,                //ADCON2レジスタの設定
                                Config3,                //ADCON3レジスタの設定
                                ConfigPort,             //ADPCFGレジスタの設定
                                ConfigScan              //ADCSSLレジスタの設定
                                );

        /// タイマ1周期 200msec

        OpenTimer1(T1_ON &                              //タイマ1ON
                                T1_GATE_OFF     &               //ゲート制御ON
                                T1_PS_1_256 &           //プリスケーラ 1/256
                                T1_SYNC_EXT_OFF &       //クロック同期制御OFF
                                T1_SOURCE_INT   ,       //クロック源:内部クロック
                                23030                   //200msec  →  200×1000×(117.92MHz/4MHz)/256=23031.25
                                );                      //PR1 = 23031 -1 = 23030


        lcd_init();                                                     // LCD初期化
        lcd_cmd(0b00001100);                            // カーソル:OFF  ブリンク:OFF

        lcd_clear();                                    // 全消去
        sprintf(Buf,"ADC Start !!%u",Count);            //arguementがないと遅い  C30のバグ?
        lcd_str(Buf);                                   //液晶表示  

        delay_ms(1000);


        ConfigIntTimer1(T1_INT_PRIOR_5 & T1_INT_ON);    //割込みレベル5 タイマ1割込みON
        EnableIntT1;                                    //割込み許可




        while(1)                                         //タイマ割込みを待つ
        {
        }

        CloseADC12();                                    //AD変換終了処理
        return 0;
}


//*********************************************************************************************
//インクルードファイル    1lcd_lib_C30.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C30コンパイラ対応、及び分散ポート対応等で変更を加えたものです。
//*********************************************************************************************

#include "p30f2012.h"

#define Clock   80000000                // 単位はHzで指定

// LCDポート設定
#define lcd_port_DB7    LATBbits.LATB12 //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6    LATBbits.LATB11 //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5    LATBbits.LATB10 //LCDのDB5(12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4    LATBbits.LATB9  //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_stb         LATFbits.LATF0  //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定  
#define lcd_rs          LATFbits.LATF1  //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定

void lcd_out(char code, char flag);
void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_str(char *str);


//********************************************************************************************
//インクルードファイル    1lcd_lib_C30.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C30コンパイラ対応、及び分散ポート対応等で変更を加えたものです。
//********************************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C30コンパイラー
//  内蔵関数は以下
//  lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//  lcd_str(str*) ----- 文字列表示 
//////////////////////////////////////////////

#include        "1lcd_lib_C30.h"
unsigned int _1usec;    // 1μsec待つに必要なウェイト回数
unsigned int _50usec;   //50μsec待つに必要なウェイト回数
unsigned long N_msec;   // 1msec待つに必要なウェイト回数



//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;

        if (flag == 0)
                lcd_rs = 1;             // 表示データの場合
        else
                lcd_rs = 0;             // コマンドデータの場合

        __delay32(_1usec);              //1μsecウェイト
                
        lcd_stb = 1;                    // strobe(E) ON (Enable)
                        
        __delay32(_1usec);              // 1μsec : strobe信号の幅

        lcd_stb = 0;                    // reset strobe
}

//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);               // 上位4ビット出力
        lcd_out(asci<<4, 0);            // 下位4ビット出力
        __delay32(_50usec);             //50μsecウェイト
}

/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                // 上位4ビット出力
        lcd_out(cmd<<4, 1);             // 下位4ビット出力
        if((cmd & 0x03) != 0)           // clear Homeの場合
        __delay32(2*N_msec);            //      2msec待ち
        else
        __delay32(_50usec);             //50μsecウェイト    
}

/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  // 初期化コマンド出力
//      __delay32(15*N_msec);           //15msecウェイト
}

/////// 文字列出力関数
void lcd_str(char* str)      
{
        while(*str)                     //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;                  //ポインタをインクリメント                          
        }       
}


/////// 初期化関数
void lcd_init(void)
{
        _1usec =(unsigned int)( Clock / 4000000);       // 1μsecに要するウェイト回数
                                                        //__delay32(N) : Nが11以下の場合でも11回ウェイト
        _50usec = (unsigned int)(Clock / 4000000 * 50); //50μescに要するウェイト回数
        N_msec = (unsigned long int)(Clock / 4000);     // 1msecに要するウェイト回数
                                                        // = Clock / 4000000*1000
        __delay32(20*N_msec);           //20msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(5*N_msec);            //5msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x20, 1);               // 4bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_cmd(0x2E);                  // DL=0 4bit mode
        lcd_cmd(0x08);                  // display off C=D=B=0
        lcd_cmd(0x0D);                  // display on C=D=1 B=0
        lcd_cmd(0x06);                  // entry I/D=1 S=0
        lcd_cmd(0x02);                  // cursor home
}

<動作結果>
 AN3端子の入力電圧(デジタルテスタ表示値)が 概略 0v、 2.5v、 5.0vの時の液晶表示を以下に示します。

AN3の入力電圧
0V 2.5V 5V

 (2)入力電圧を液晶に表示(dsPIC30F4013)
  dsPIC30F4013の内臓ADコンバータからAD変換値を読込み、値を液晶に表示した例を紹介します。


 <試作品仕様>
  ・ dsPIC30F4013のAN1端子から内臓AD変換器をつかい電圧を読み込む
  ・ リファレンス電圧は+5V(PICの電源電圧)とする。
  ・ 液晶には以下を200msec毎に表示する。
     @ 1行目 …… AD変換値
     A 2行目 …… 入力電圧(単位:ボルト)


 <試作品回路図>
  dsPIC30F4013の場合の回路図を以下にしめします。(→回路図のPDFファイル



<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています

   <プログラム例>

///************************************************************/
// ADコンバータ出力の液晶表示
//            dsPIC30F4013
//************************************************************/
#include        "p30f4013.h"
#include        "1lcd_lib_C30.h"
#include        "adc12.h"
#include        "stdio.h"


_FOSC(CSW_FSCM_OFF & XT_PLL8);                          // (10MHz)x8=80MHz
_FWDT(WDT_OFF);
_FBORPOR(PBOR_ON & BORV_42 & PWRT_64 & MCLR_EN);
_FGS(CODE_PROT_OFF); 

unsigned int Config1 =          //ADCON1レジスタの設定
        ADC_MODULE_ON &         //ADON bit15=1 : ADコンバータモジュール → ON  //AD Module On/Off
        ADC_IDLE_CONTINUE &     //ADSIL bit13=0 : アイドル時の動作 → 動作継続 //Idle Mode Operation
        ADC_FORMAT_INTG &       //FORM bit9-8=00 :出力データのフォーマット → 整数 //Result Output Format
        ADC_CLK_AUTO &          //SSRC bit5-7=111 :変換開始トリガ設定  //Conversion Trigger Source
                                                        //       →ADCON3のSAMCによるクロック(サンプルホールド)が終了後変換自動開始
        ADC_AUTO_SAMPLING_OFF & //ASAM bit2=1 : ADサンプリング自動開始→手動開始 //Auto Sampling Select
        ADC_SAMP_OFF;           //SAMP bit1=0 : サンプリング手動制御→OFF //Sample Enable
                                //  (例)ASAM = 0(ADC_AUTO_SAMPLING_OFF) の時 SAMP=1(ADC_SAMP_ON)で変換開始
                                //DONE bit0     : AD変換終了フラグ(AD変換が終了すると1が立つ、 書き込み不可)

unsigned int Config2 =          //ADCON2レジスタの設定
        ADC_VREF_AVDD_AVSS &    //VCFG bit13-15=000: S/Hアンプのリファレンス設定: 基準電圧Vdd、シングルエンド //Voltage Reference
        ADC_SCAN_OFF &          //CSCNA bit10=0 : MUX交互自動スキャン制御→オフ //Scan Section
        ADC_SAMPLES_PER_INT_1 & //SMPI bit2-5 : 割込み頻度→1回毎 //Number of Samples between Interrupts
        ADC_ALT_BUF_OFF &       //BUFM bit1=0: 交互バッファー制御→なし //Buffer mode Select
        ADC_ALT_INPUT_OFF;      //ALTS bit0=0: AD入力の複数バッファーへの格納//Alternate Input sample Mode Select(

unsigned int Config3 =          //ADCON3レジスタの設定
        ADC_SAMPLE_TIME_8 &     //SAMC bit8-12 :サンプルホールド時間 → 8サイクル(TAD)//Auto Sample Time bits
        ADC_CONV_CLK_SYSTEM &   //ADRC bit7=0 :AD変換クロック→システムクロック //Conversion Clock Source Select
        ADC_CONV_CLK_32Tcy;     //ADCS bit0-5 :変換クロック数→32Tcy(設定のMAXを選択) //Conversion Clock Select

unsigned int ConfigPort =       //ADPCFGレジスタの設定 ANLOG/DIGITAl Pin Select
                                //ex1.  ENABLE_ALL_ANA   ex2. ENABLE_ALL_DIG   ex3. ENABLE_AN0_ANA & ENABLE_AN1_ANA
        ENABLE_AN1_ANA;         //AN1 → アナログポート

unsigned int ConfigScan =       //ADCSSLレジスタの設定         Scan Channel Select
        SCAN_NONE;              //ADCSLL = 0x0000 : 自動スキャン→スキャンせず

unsigned int Channel1 =         //ADCHSレジスタの設定
        ADC_CH0_POS_SAMPLEA_AN1 &  //マルチプレクサA(S/Hアンプ)のVref+への接続チャンネル → チャンネル1
        ADC_CH0_NEG_SAMPLEA_NVREF; //マルチプレクサA(S/Hアンプ)のVref-への接続チャンネル → Vss
        

unsigned int Count;
unsigned int AdcValue;
char Buf[17];                                        //文字列のバッファー用レジスタ


void delay_ms(unsigned int);
void AdcFunc(void);



void delay_ms(unsigned int N)                           //ウェイト関数
{
        __delay32(Clock/4000*N);
}
        
void AdcFunc(void)                                      // AD変換読み取り & 液晶表示
{
        float Volt;
        unsigned int    I;      
        unsigned int    F;
        
                SetChanADC12(Channel1);                 //Vref-(RB1、AN1) → GND
                ADCON1bits.SAMP =1;                     //サンプリング開始
                                                        //サンプルホールド時間:8TAD (ADCON3のSAMC<3:0>)
                                                        //変換の自動開始
                                                        //変換時間:31TAD (ADCON3のADCS<5:0>)
        //      while(BusyADC12());
                while(!ADCON1bits.DONE);                //AD変換終了フラグが1になるまでまつ


        //      AdcValue = ReadADC12(0);                //AD変換値読込み(読込みが遅い) C30のバグ?
                AdcValue = ADCBUF0;                     //AD変換値読込み(読込みが早い) //バッファー0の読み出し


                lcd_clear();                            //全消去
        
                sprintf(Buf,"AdV=%u",AdcValue);         //バッファーに文字列をセット
                lcd_str(Buf);                           // 開始メッセージ1行目表示

                Count++;
                Volt =(float)AdcValue/4095*5;
                I = (unsigned int) Volt;
                F = (unsigned int)(( Volt - I)*1000);                   
                lcd_cmd(0xC0);                          //2行目の先頭へ
                sprintf(Buf,"Volt=%u.%u[V]",I,F);       //文字列としてバッファーに収納
                lcd_str(Buf);                           // 開始メッセージ1行目表示

                delay_ms(200);                          //200msec毎に再表示

}

/// メイン関数
int     main(void) {

        TRISB = 0b0000000000000010;                     // AD入力のbit1(AN1 RB1)のみ入力
        TRISF = 0;


                        
        OpenADC12(
                     Config1,                //ADCON1レジスタの設定
                     Config2,                //ADCON2レジスタの設定
                     Config3,                //ADCON3レジスタの設定
                     ConfigPort,             //ADPCFGレジスタの設定
                     ConfigScan              //ADCSSLレジスタの設定
                               );


        lcd_init();                         // LCD初期化
        lcd_cmd(0b00001100);                // カーソル:OFF  ブリンク:OFF

        lcd_clear();                        // 全消去
        sprintf(Buf,"ADC Start !!%u",Count);//arguementがないと遅い  C30のバグ?
        lcd_str(Buf);                       //液晶表示  

        delay_ms(1000);

        while(1)
        {
                AdcFunc();                   // AD変換読み取り & 液晶表示                                              
        }

        CloseADC12();                        //AD変換終了処理
        return 0;
}


//*********************************************************************************************
//インクルードファイル    1lcd_lib_C30.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C30コンパイラ対応、及び分散ポート対応等で変更を加えたものです。
//*********************************************************************************************

#include "p30f4013.h"

#define Clock   80000000                // 単位はHzで指定

// LCDポート設定
#define lcd_port_DB7    LATBbits.LATB12 //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6    LATBbits.LATB11 //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5    LATBbits.LATB10 //LCDのDB5(12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4    LATBbits.LATB9  //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_stb         LATFbits.LATF0  //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定  
#define lcd_rs          LATFbits.LATF1  //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定

void lcd_out(char code, char flag);
void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_str(char *str);


//**********************************************************************************************
//インクルードファイル    1lcd_lib_C30.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C30コンパイラ対応、及び分散ポート対応等で変更を加えたものです。
//**********************************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C30コンパイラー
//  内蔵関数は以下
//  lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//  lcd_str(str*) ----- 文字列表示 
//////////////////////////////////////////////

#include        "1lcd_lib_C30.h"
unsigned int _1usec;    // 1μsec待つに必要なウェイト回数
unsigned int _50usec;   //50μsec待つに必要なウェイト回数
unsigned long N_msec;   // 1msec待つに必要なウェイト回数



//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;

        if (flag == 0)
                lcd_rs = 1;             // 表示データの場合
        else
                lcd_rs = 0;             // コマンドデータの場合

        __delay32(_1usec);              //1μsecウェイト
                
        lcd_stb = 1;                    // strobe(E) ON (Enable)
                        
        __delay32(_1usec);              // 1μsec : strobe信号の幅

        lcd_stb = 0;                    // reset strobe
}

//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);               // 上位4ビット出力
        lcd_out(asci<<4, 0);            // 下位4ビット出力
        __delay32(_50usec);             //50μsecウェイト
}

/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                // 上位4ビット出力
        lcd_out(cmd<<4, 1);             // 下位4ビット出力
        if((cmd & 0x03) != 0)           // clear Homeの場合
        __delay32(2*N_msec);            //      2msec待ち
        else
        __delay32(_50usec);             //50μsecウェイト    
}

/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  // 初期化コマンド出力
//      __delay32(15*N_msec);           //15msecウェイト
}

/////// 文字列出力関数
void lcd_str(char* str)      
{
        while(*str)                     //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;                  //ポインタをインクリメント                          
        }       
}


/////// 初期化関数
void lcd_init(void)
{
        _1usec =(unsigned int)( Clock / 4000000);       // 1μsecに要するウェイト回数
                                                        //__delay32(N) : Nが11以下の場合でも11回ウェイト
        _50usec = (unsigned int)(Clock / 4000000 * 50); //50μescに要するウェイト回数
        N_msec = (unsigned long int)(Clock / 4000);     // 1msecに要するウェイト回数
                                                        // = Clock / 4000000*1000
        __delay32(20*N_msec);           //20msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(5*N_msec);            //5msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x20, 1);               // 4bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_cmd(0x2E);                  // DL=0 4bit mode
        lcd_cmd(0x08);                  // display off C=D=B=0
        lcd_cmd(0x0D);                  // display on C=D=1 B=0
        lcd_cmd(0x06);                  // entry I/D=1 S=0
        lcd_cmd(0x02);                  // cursor home
}

<動作結果>
 AN1端子の入力電圧(デジタルテスタ表示値)が 概略 0v、 2.5v、 5.0vの時の液晶表示を以下に示します。

AN1端子の入力電圧
0V 2.5V 5V



■ C30コンパイラ PIC24編
  入力電圧を液晶に表示する。

 PIC24FJ64GA002の内臓ADコンバータからAD変換値を読込み、値を液晶に表示した例を紹介します。


 <試作品仕様>
  ・ PIC24FJ64GA002のAN0端子から内臓AD変換器をつかい電圧を読み込む
  ・ リファレンス電圧は+3.3V(PICの電源電圧)とする。
  ・ 液晶には以下を200msec毎に表示する。
     @ 1行目 …… AD変換値
     A 2行目 …… 入力電圧(単位:ボルト)


 <試作品回路図>
  PIC24FJ64GA002の場合の回路図を以下にしめします。(→回路図のPDFファイル


<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています





<プログラム例>
///************************************************************/
//*  AD変換 液晶表示
//*      PIC24FJ64GA002   
//************************************************************/
#include        "p24FJ64GA002.h"
#include        <stdio.h>
//#include        <adc10.h>  //★(dsPICと同じようには)インクルードできない
#include    <timer.h>

#include        "1lcd_lib_C30.h"
#include        "1lcd_lib_c30.c"



/// コンフィギュレーション ビットの設定
_CONFIG1( JTAGEN_OFF &  //JTAGポート: OFF
                         GCP_OFF &      //コードプロテクト: OFF
                        GWRP_OFF &      //書き込みプロテクト: OFF
                        BKBUG_OFF &     //バックグランドデバック: OFF
                        COE_OFF &       //クリップオン エミュレーション: OFF 
                        ICS_PGx1&       //ICDピンの選択: EMUC/EMUDをPGC1/PGD1と共用
                        FWDTEN_OFF )//ウォッチドックタイマ: OFF 


_CONFIG2( IESO_OFF &    // 2速度スタートアップ機能:OFF
                FNOSC_FRCPLL &  //内臓高速RC発振(8MHZ)回路 + 4倍PLL → 32MHz(= 8MHz × 4)
                FCKSM_CSDCMD &  //クロック切替え制御:OFF クロックモニタ:OFF
                OSCIOFNC_OFF &  //OSCO/RC15 function: OSCO or Fosc/2
                IOL1WAY_OFF &   //RP Register Protection: Unlimited Writes To RP Registers
                I2C1SEL_PRI &   //I2C1 pins Select: Use Primary I2C1 pins
                POSCMOD_NONE)   //発振回路モード Oscillator Selection:  Primary disabled


unsigned int AdcValue;
char Buf[17];   //文字列のバッファー用レジスタ
unsigned int Count=0;


void delay_ms(unsigned int N)   //ウェイト関数
{
        __delay32(Clock/4000*N);
}

void AdcFunc(void)              // AD変換読み取り & 液晶表示
{
        float Volt;
        unsigned int    I;      
        unsigned int    F;

        AD1CON1bits.SAMP =1;            //サンプリング開始
        while(!AD1CON1bits.DONE);       //AD変換終了フラグがたつ(1になるまで)待つ
//      delay_ms(1);


        AdcValue = ADC1BUF0;            //ADC1のAN0のバッファーからAD変換結果を読込む

        lcd_clear();            //全消去
        sprintf(Buf,"AdV=%u",AdcValue); //バッファーに文字列をセット
        lcd_str(Buf);   // 開始メッセージ1行目表示
        
        Volt =(float)AdcValue/1024*3.3;
        I = (unsigned int) Volt;
        F = (unsigned int)(( Volt - I)*1000);                   
        lcd_cmd(0xC0);          //2行目の先頭へ
        sprintf(Buf,"Volt=%u.%u[V]",I,F);       //文字列としてバッファーに収納
        lcd_str(Buf);           // 開始メッセージ1行目表示
}

void _ISR _T1Interrupt(void)    //タイマ1割込み
{
        IFS0bits.T1IF = 0;      //フラグクリア
        AdcFunc();      // AD変換読み取り & 液晶表示                                              
}


/// メイン関数
int     main(void) 
{
        TRISA = 0xFFFF;         //Aポートを入力モードに設定
        TRISB = 0;              //Bポートを出力モードに設定  

        //AD1CON1レジスタの設定        
        AD1CON1bits.ADON = 1;   //A/Dコンバータモジュール有効
        AD1CON1bits.ADSIDL = 0; //アイドルモード中もモジュール動作継続
        AD1CON1bits.FORM1 = 0;  //AD1CON1bits.FORM0 と2ビットでセット
        AD1CON1bits.FORM0 = 0;  //00: 符号なし整数 (参考)11:符号なし固定少数、10:固定少数、01:整数
                                //★ Michrochip PIC24FJ64GA002のデータシートでは00がIntegerとなっているがUnsigned Integerの誤植である。 
        AD1CON1bits.SSRC2 = 1;  //AD1CON1bits.SSRC2-AD1CON1bits.SSRC0 でセット
        AD1CON1bits.SSRC1 = 1;  //111: 内蔵カウンタでサンプリングを終了させ変換を開始する
        AD1CON1bits.SSRC0 = 1;  //(参考)000: SAMPビットでサンプリングを終了し変換を開始する
        AD1CON1bits.ASAM = 0;   //SAMPビットのセットでサンプリングを開始する。 (参考)1: 自動開始(前の変換終了後すぐサンプリングを開始する)
        AD1CON1bits.SAMP = 0;   //サンプリング停止

        //AD1CON2レジスタの設定
        AD1CON2bits.VCFG2 = 0;  //AD1CON2bits.VCFG2 - AD1CON2bits.VCFG0(VCFG<2:0>)の3ビットでセット
        AD1CON2bits.VCFG1 = 0;  //000:リファレンス電圧 → Vdd -Vss
        AD1CON2bits.VCFG0 = 0;  //(参考)001:リファレンス電圧 → 外部入力 - Vss 他
        AD1CON2bits.CSCNA = 1;  //マルチプレクサMUXAでのスキャン: する
        AD1CON2bits.SMPI3 = 0;  //AD1CON2bits.SMPI3 - AD1CON2bits.SMPI0(SMPI<3:0>)の4ビットでセット
        AD1CON2bits.SMPI2 = 0;  //0000: AD変換完了毎の割り込み発生(割り込み有効の場合)
        AD1CON2bits.SMPI1 = 0;  //(参考)0011: 4サンプルのAD変換終了後       割り込み発生(割り込み有効の場合)
        AD1CON2bits.SMPI0 = 0;  //
        AD1CON2bits.BUFM = 0;   //バッファーを1個の16ワードバッファとする。 (参考)1: 2組の8ワードバッファーとする
        AD1CON2bits.ALTS = 0;   //常にMUXAを入力マルチプレクサにする (参考)1: MUXA,MUXBを交互につかう

        //AD1CON3レジスタの設定
        AD1CON3bits.ADRC = 0;   //AD変換クロック源:システムクロック (参考)1: A/D内臓RCクロック
        AD1CON3bits.SAMC4 = 1;  //AD1CON3bits.SAMC4 - AD1CON3bits.SAMC0(SAMC<4:0>)の5ビットでセット
        AD1CON3bits.SAMC3 = 1;  //アクイジションタイム(Tad(クロック周期)×N)設定
        AD1CON3bits.SAMC2 = 1;  //1111: 31Tad
        AD1CON3bits.SAMC1 = 1;  //(参考)0001: 1Tad    0010: 2Tad    0011: 3Tad  ・・・・
        AD1CON3bits.SAMC0 = 1;  //
        AD1CON3bits.ADCS7 = 0;  //AD1CON3bits.ADCS7 - AD1CON3bits.ADCS0(ADCS<7:0>)の8ビットでセット
        AD1CON3bits.ADCS6 = 0;  //AD変換のクロックとクロック源の関係
        AD1CON3bits.ADCS5 = 0;  //0000 0101: 1Tad = 5Tcy        
        AD1CON3bits.ADCS4 = 0;  //(参考) 0000 0000: 1Tad = 0.5Tcy
        AD1CON3bits.ADCS3 = 0;  //      0000 0001: 1Tad = 1.0Tcy
        AD1CON3bits.ADCS2 = 1;  //          0000 0010: 1Tad = 1.5Tcy
        AD1CON3bits.ADCS1 = 0;  //                                ・・・・    
        AD1CON3bits.ADCS0 = 1;  //     1111 1111: 1Tad = 128Tcy

        //AD1CHSレジスタの設定
        AD1CHSbits.CH0NB = 0;   //マルチプレクサMUXB用負側入力選択ビット: VR-  (参考)1: AN1
        AD1CHSbits.CH0SB3 = 0;  //AD1CHSbits.CH0SB3 - AD1CHSBbits.CH0SB0(<CH0SB<3:0>)の4ビットでセット
        AD1CHSbits.CH0SB2 = 0;  //マルチプレクサMUXBの正側入力選択
        AD1CHSbits.CH0SB1 = 0;  //0000: AN0
        AD1CHSbits.CH0SB0 = 0;  //(参考)0001: AN1  0011 AN2    ....  1111: AN15
        AD1CHSbits.CH0NA = 0;   //マルチプレクサMUXA用負側入力選択ビット: VR-  (参考)1: AN1
        AD1CHSbits.CH0SA3 = 0;  //AD1CHSbits.CH0SA3 - AD1CHSbits.CH0SA0(<CH0SA<3:0>)の4ビットでセット
        AD1CHSbits.CH0SA2 = 0;  //マルチプレクサMUXAの正側入力選択
        AD1CHSbits.CH0SA1 = 0;  //0000: AN0
        AD1CHSbits.CH0SA0 = 0;  //(参考)0001: AN1  0011 AN2    ....  1111: AN15

        //AD1PCFGレジスタの設定  
        // ★デバイスリセットでは全ビット0となるためデフォルトではアナログ入力となるのでデジタルで使う多重ピンは、コンフィグレーションでデジタル設定が必要!! 
        //PIC24FJ64GA002にはないピン・設定も特に必要ないが設定
        AD1PCFGbits.PCFG15 = 1;//RA15/AN15アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
//      AD1PCFGbits.PCFG14 = 1;//RA14/AN14アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
//      AD1PCFGbits.PCFG13 = 1;//RA13/AN13アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG12 = 1;//RA12/AN12アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG11 = 1;//RA11/AN11アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG10 = 1;//RA10/AN10アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ    
        AD1PCFGbits.PCFG9 = 1;//RA9/AN9アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
//      AD1PCFGbits.PCFG8 = 1;//RA8/AN8アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
//      AD1PCFGbits.PCFG7 = 1;//RA7/AN7アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
//      AD1PCFGbits.PCFG6 = 1;//RA6/AN6アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG5 = 1;//RA5/AN5アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG4 = 1;//RA4/AN4アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG3 = 1;//RA3/AN3アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG2 = 1;//RA2/AN2アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG1 = 1;//RA1/AN1アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG0 = 0;//RA0/AN0アナログ入力orデジタル入力選択: アナログ (参考)0: デジタル


        //      AD1CSSLレジスタの設定
        //読み込むチャンネル(入力端子)をセットする
        AD1CSSLbits.CSSL15 = 0; //AN15をMUXAでスキャンしない (参考)1: スキャンする
//      AD1CSSLbits.CSSL14 = 0; //AN15をMUXAでスキャンしない (参考)1: スキャンする
//      AD1CSSLbits.CSSL13 = 0; //AN13をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL12 = 0; //AN12をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL11 = 0; //AN11をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL10 = 0; //AN10をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL9 = 0;  //AN9をMUXAでスキャンしない (参考)1: スキャンする
//      AD1CSSLbits.CSSL8 = 0;  //AN8をMUXAでスキャンしない (参考)1: スキャンする
//      AD1CSSLbits.CSSL7 = 0;  //AN7をMUXAでスキャンしない (参考)1: スキャンする
//      AD1CSSLbits.CSSL6 = 0;  //AN6をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL5 = 0;  //AN5をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL4 = 0;  //AN4をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL3 = 0;  //AN3をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL2 = 0;  //AN2をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL1 = 0;  //AN1をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL0 = 1;  //AN0をMUXAでスキャンする (参考)0: スキャンしない

        


        /// タイマ1周期 200msec

        OpenTimer1(T1_ON &              //タイマ1ON
                        T1_GATE_OFF     &       //ゲート制御ON
                        T1_PS_1_64 &    //プリスケーラ 1/64
                        T1_SYNC_EXT_OFF &       //クロック同期制御OFF
                        T1_SOURCE_INT,          //クロック源:内部クロック
                        24999                   //200msec  →  200×1000×(32MHz/4MHz)/64=25000
                        );                              //PR1 = 25000 -1 = 24999



        lcd_init();                             // LCD初期化
        lcd_cmd(0b00001100);    // カーソル:OFF  ブリンク:OFF

        lcd_clear();            // 全消去
        sprintf(Buf,"ADC Start !!%u",Count);//arguementがないと遅い  C30のバグ?
        lcd_str(Buf);                   //液晶表示  
        delay_ms(1000);


        ConfigIntTimer1(T1_INT_PRIOR_5 & T1_INT_ON);    //割込みレベル5 タイマ1割込みON
        EnableIntT1;                                    //割込み許可

        while(1)        //タイマ割込みを待つ
        {
        }

        CloseTimer1();
        return 0;
}


//*************************************************************************
//インクルードファイル    1lcd_lib_C30.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C30コンパイラ対応等でに変更したものです。
//*************************************************************************

#include "p24FJ64GA002.h"

#define Clock   32000000        // 単位はHzで指定


// LCDポート設定
#define lcd_port_DB7    LATBbits.LATB15 //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6    LATBbits.LATB14 //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5    LATBbits.LATB13 //LCDのDB5(12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4    LATBbits.LATB12 //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_stb                 LATBbits.LATB1  //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定  
#define lcd_rs                  LATBbits.LATB0  //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定


void lcd_out(char code, char flag);
void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_str(char *str);



//**************************************************************************
//インクルードファイル    1lcd_lib_C30.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C30コンパイラ対応等で変更したものです。
//**************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C30コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//    lcd_str(str*) ----- 文字列表示 
//////////////////////////////////////////////

#include        "1lcd_lib_C30.h"
unsigned int _1usec;    // 1μsec待つに必要なウェイト回数
unsigned int _50usec;   //50μsec待つに必要なウェイト回数
unsigned long N_msec;   // 1msec待つに必要なウェイト回数



//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;

        if (flag == 0)
                lcd_rs = 1;                     // 表示データの場合
        else
                lcd_rs = 0;                     // コマンドデータの場合

        __delay32(_1usec);              //1μsecウェイト
                
        lcd_stb = 1;                    // strobe(E) ON (Enable)
                        
        __delay32(_1usec);              // 1μsec : strobe信号の幅

        lcd_stb = 0;                    // reset strobe
}

//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);               // 上位4ビット出力
        lcd_out(asci<<4, 0);    // 下位4ビット出力
        __delay32(_50usec);             //50μsecウェイト
}

/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                // 上位4ビット出力
        lcd_out(cmd<<4, 1);             // 下位4ビット出力
        if((cmd & 0x03) != 0)   // clear Homeの場合
        __delay32(2*N_msec);    //      2msec待ち
        else
        __delay32(_50usec);             //50μsecウェイト    
}

/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  // 初期化コマンド出力
//      __delay32(15*N_msec);   //15msecウェイト
}

/////// 文字列出力関数
void lcd_str(char* str)      
{
        while(*str)                             //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;                          //ポインタをインクリメント                          
        }       
}


/////// 初期化関数
void lcd_init(void)
{
        _1usec =(unsigned int)( Clock / 4000000);       // 1μsecに要するウェイト回数
                                                                                                //__delay32(N) : Nが11以下の場合でも11回ウェイト
        _50usec = (unsigned int)(Clock / 4000000 * 50); //50μescに要するウェイト回数

        N_msec = (unsigned long int)(Clock / 4000);             // 1msecに要するウェイト回数
                                                                                                        // = Clock / 4000000*1000
        __delay32(20*N_msec);   //20msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(5*N_msec);    //5msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x20, 1);               // 4bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_cmd(0x2E);                  // DL=0 4bit mode
        lcd_cmd(0x08);                  // display off C=D=B=0
        lcd_cmd(0x0D);                  // display on C=D=1 B=0
        lcd_cmd(0x06);                  // entry I/D=1 S=0
        lcd_cmd(0x02);                  // cursor home
}

















<動作結果>
 液晶の下に写っているのはAN0の端子電圧を表示しているデジタルテスターです。

AN0の入力電圧
0V 1.5V 3.3V





■ C32コンパイラ PIC32MX編
  入力電圧を液晶に表示する。

 PIC32MX460F512L内臓ADコンバータからAD変換値を読込み、値を液晶に表示した例を紹介します。


 <試作品仕様>
  ・ PIC32MX460F512LのAN0端子から内臓AD変換器をつかい電圧を読み込む
  ・ リファレンス電圧は+3.3V(PICの電源電圧)とする。
  ・ 液晶には以下を100msec毎に表示する。
     @ 1行目 …… AD変換値
     A 2行目 …… 入力電圧(単位:ボルト)


 <試作品回路図>
  PIC32MX460F512Lの場合の回路図を以下にしめします。(→回路図のPDFファイル



<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています.
          ・ QFPのPIC32MX460F512Lは、マイクロチップから開発用ターゲットボードExplore 16のCPUボードとして、販売されている
            PIM(Plug in Moduke)に実装されているものを使っています。

          ・使用しているユニバーサルキバンは自作のユニバーサルキバンです。



          

   <プログラム例>


//    ADコンバータ読み込み・値の液晶表示
//                 PIC32MX460F512L 

#include <proc/p32mx460f512l.h>         //PIC32MX460F512L
#include <plib.h>               // PIC32 peripheral library 
                                                        //for SYSTEMConfigPerformance()

#include        "1lcd_lib_C32.h"

// コンフィギュレーション設定
// CPU=80MHz Peri=80MHz,HS+PLL,Divider=1/2,PLL=x20,WDT=Off
#pragma config FNOSC=PRIPLL, POSCMOD=HS, FPLLIDIV=DIV_2
#pragma config FPLLMUL=MUL_20, FPBDIV=DIV_1, FPLLODIV=DIV_1
#pragma config FWDTEN=OFF, ICESEL=ICS_PGx2


char Buf[17];   //文字列のバッファー用レジスタ


void AdcFunc(void)              // AD変換読み取り & 液晶表示
{
        float Volt;
        unsigned int    I;      
        unsigned int    F;
                unsigned int AdcValue;

        AD1CON1bits.SAMP =1;            //サンプリング開始
        while(!AD1CON1bits.DONE);       //AD変換終了フラグがたつ(1になるまで)待つ

        AdcValue = ADC1BUF0;            //ADC1のAN0のバッファーからAD変換結果を読込む

        lcd_clear();            //全消去
        sprintf(Buf,"AdV=%u",AdcValue); //バッファーに文字列をセット
        lcd_str(Buf);   // 開始メッセージ1行目表示
        
        Volt =(float)AdcValue/1024*3.3;
        I = (unsigned int) Volt;
        F = (unsigned int)(( Volt - I)*1000);                   
        lcd_cmd(0xC0);          //2行目の先頭へ
        sprintf(Buf,"Volt=%u.%u[V]",I,F);       //文字列としてバッファーに収納
        lcd_str(Buf);           // 開始メッセージ1行目表示
}




void __ISR(4,ipl2)T1Hander(void)        //タイマ1割込 100msec毎
{
        mT1ClearIntFlag();              //フラグクリア
        AdcFunc();      // AD変換読み取り & 液晶表示    
}

int main(void)
{
        SYSTEMConfigPerformance(80000000);      // システム最適化
        LATBbits.LATB0 = 1;     //RB0/AN0 を入力ポートに設定
        TRISE = 0;              //Eポートを出力モードに設定

    //AD1CON1レジスタの設定        
                AD1CON1bits.ON = 1;             //A/Dコンバータモジュール有効
                AD1CON1bits.FRZ = 0;    //デバッグモードに於いても動作継続
        AD1CON1bits.SIDL = 0; //アイドルモード中もモジュール動作継続
        AD1CON1bits.FORM2 = 0;  //AD1CON1bits.FORM2-AD1CON1bits.FORM0のセットで出力データ形式指定 → 000:16ビット符号なし整数形式
                AD1CON1bits.FORM1 = 0;  //011:符号付固定16ビット小数 010:固定小数16ビット 001:符号付き整数16ビット 000:16ビット符号なし整数                
        AD1CON1bits.FORM0 = 0;  //111:符号付32ビット固定小数 110:32ビット固定小数 101:符号付32ビット整数 100=32ビット符号なし整数
                                //★ Michrochip データシートDS61104 では000、100がIntegerとなっているがUnsigned Integerの誤植である。 
        AD1CON1bits.SSRC2 = 1;  //AD1CON1bits.SSRC2-AD1CON1bits.SSRC0 のセットでトリガーソースを指定
        AD1CON1bits.SSRC1 = 1;  //111: 内蔵カウンタでサンプリングを終了させ変換を開始する
        AD1CON1bits.SSRC0 = 1;  //(参考)000: SAMPビットでサンプリングを終了し変換を開始する
                AD1CON1bits.CLRASAM = 0;//AD変換割り込み時の変換停止 0:次の変換値でオーバーライト 
        AD1CON1bits.ASAM = 0;   //SAMPビットのセットでサンプリングを開始する。(参考)1: 自動開始(前の変換終了後すぐサンプリングを開始する)
        AD1CON1bits.SAMP = 0;   //サンプリング停止



        //AD1CON2レジスタの設定
        AD1CON2bits.VCFG2 = 0;  //リファレンス選択//AD1CON2bits.VCFG2 - AD1CON2bits.VCFG0(VCFG<2:0>)の3ビットでセット
        AD1CON2bits.VCFG1 = 0;  //000:リファレンス電圧 → Vdd -Vss
        AD1CON2bits.VCFG0 = 0;  //(参考)001:リファレンス電圧 → 外部入力 - Vss 他
                AD1CON2bits.OFFCAL = 0; //較正モード設定 0:サンプルホールドアンプSHAの入力はAD1CHSレジスタとAD1CSSLレジスタで制御される
        AD1CON2bits.CSCNA = 1;  //マルチプレクサMUXAでのスキャン: する
                AD1CON2bits.SMPI3 = 0;  //割り込みタイミング AD1CON2bits.SMPI3 - AD1CON2bits.SMPI0(SMPI<3:0>)の4ビットでセット
        AD1CON2bits.SMPI2 = 0;  //0000: AD変換完了毎の割り込み発生(割り込み有効の場合)
        AD1CON2bits.SMPI1 = 0;  //(参考)0011: 4サンプルのAD変換終了後       割り込み発生(割り込み有効の場合)
        AD1CON2bits.SMPI0 = 0;  //
        AD1CON2bits.BUFM = 0;   //バッファーを1個の16ワードバッファとする。 (参考)1: 2組の8ワードバッファーとする
        AD1CON2bits.ALTS = 0;   //常にMUXAを入力マルチプレクサにする (参考)1: MUXA,MUXBを交互につかう



 //AD1CON3レジスタの設定
        AD1CON3bits.ADRC = 0;   //AD変換クロック源選択//0: PBCLK(Peripheral Bus Clock) (参考)1: A/D内臓RCクロック
        AD1CON3bits.SAMC4 = 1;  //AD1CON3bits.SAMC4 - AD1CON3bits.SAMC0(SAMC<4:0>)の5ビットでセット
        AD1CON3bits.SAMC3 = 1;  //アクイジションタイム(Tad(クロック周期)×N)設定(ホールドキャパシタ充電所要時間)
        AD1CON3bits.SAMC2 = 1;  //1111: 31Tad
        AD1CON3bits.SAMC1 = 1;  //(参考)0001: 1Tad    0010: 2Tad    0011: 3Tad  ・・・・
        AD1CON3bits.SAMC0 = 1;  //
        AD1CON3bits.ADCS7 = 0;  //AD変換時間の設定/AD1CON3bits.ADCS7 - AD1CON3bits.ADCS0(ADCS<7:0>)の8ビットでセット
                                                                //AD変換完了フラグAD1CON1bits.DONEにより、AD変換完了を検知する場合は設定不要
        AD1CON3bits.ADCS6 = 0;  //AD変換完了までののクロック数選択ビット
        AD1CON3bits.ADCS5 = 0;  //0000 0101: 1Tad = 6Tpb  (Tpb: PBCLKの周期)      
        AD1CON3bits.ADCS4 = 0;  //(参考) 0000 0000: 1Tad = 2Tpb
        AD1CON3bits.ADCS3 = 0;  //      0000 0001: 1Tad = 3Tpb
        AD1CON3bits.ADCS2 = 1;  //      0000 0010: 1Tad = 4Tpb
        AD1CON3bits.ADCS1 = 0;  //                                ・・・・    
        AD1CON3bits.ADCS0 = 1;  //     1111 1111: 1Tad = 512Tpb

 //AD1CHSレジスタの設定 //SHAの+端子とー端子への接続(ポート)設定
            AD1CHSbits.CH0NB = 0;   //マルチプレクサMUXB用負側入力選択ビット: VR-  (参考)1: AN1
        AD1CHSbits.CH0SB3 = 0;  //AD1CHSbits.CH0SB3 - AD1CHSBbits.CH0SB0(<CH0SB<3:0>)の4ビットでセット
        AD1CHSbits.CH0SB2 = 0;  //マルチプレクサMUXBの正側入力選択
        AD1CHSbits.CH0SB1 = 0;  //0000: AN0
        AD1CHSbits.CH0SB0 = 0;  //(参考)0001: AN1  0011 AN2    ....  1111: AN15
      
                AD1CHSbits.CH0NA = 0;   //マルチプレクサMUXA用負側入力選択ビット: VR-  (参考)1: AN1
        AD1CHSbits.CH0SA3 = 0;  //AD1CHSbits.CH0SA3 - AD1CHSbits.CH0SA0(<CH0SA<3:0>)の4ビットでセット
        AD1CHSbits.CH0SA2 = 0;  //マルチプレクサMUXAの正側入力選択
        AD1CHSbits.CH0SA1 = 0;  //0000: AN0
        AD1CHSbits.CH0SA0 = 0;  //(参考)0001: AN1  0011 AN2    ....  1111: AN15

//AD1PCFGレジスタの設定 // ポートのアナログデジタル 
        // ★デバイスリセットでは全ビット0となるためデフォルトではアナログ入力となるのでデジタルで使う多重ピンは、コンフィグレーションでデジタル設定が必要!! 
                AD1PCFGbits.PCFG15 = 1;//RB15/AN15アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
                AD1PCFGbits.PCFG14 = 1;//RB14/AN14アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
                AD1PCFGbits.PCFG13 = 1;//RB13/AN13アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG12 = 1;//RB12/AN12アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG11 = 1;//RB11/AN11アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG10 = 1;//RB10/AN10アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ    
        AD1PCFGbits.PCFG9 = 1;//RB9/AN9アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
                AD1PCFGbits.PCFG8 = 1;//RB8/AN8アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
                AD1PCFGbits.PCFG7 = 1;//RB7/AN7アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
                AD1PCFGbits.PCFG6 = 1;//RB6/AN6アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG5 = 1;//RB5/AN5アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG4 = 1;//RB4/AN4アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG3 = 1;//RB3/AN3アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG2 = 1;//RB2/AN2アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG1 = 1;//RB1/AN1アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG0 = 0;//RB0/AN0アナログ入力orデジタル入力選択: アナログ (参考)1: デジタル


        //      AD1CSSLレジスタの設定
        //読み込むチャンネル(入力端子)をセットする
        AD1CSSLbits.CSSL15 = 0; //AN15をMUXAでスキャンしない (参考)1: スキャンする
                AD1CSSLbits.CSSL14 = 0; //AN15をMUXAでスキャンしない (参考)1: スキャンする
                AD1CSSLbits.CSSL13 = 0; //AN13をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL12 = 0; //AN12をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL11 = 0; //AN11をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL10 = 0; //AN10をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL9 = 0;  //AN9をMUXAでスキャンしない (参考)1: スキャンする
                AD1CSSLbits.CSSL8 = 0;  //AN8をMUXAでスキャンしない (参考)1: スキャンする
                AD1CSSLbits.CSSL7 = 0;  //AN7をMUXAでスキャンしない (参考)1: スキャンする
                AD1CSSLbits.CSSL6 = 0;  //AN6をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL5 = 0;  //AN5をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL4 = 0;  //AN4をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL3 = 0;  //AN3をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL2 = 0;  //AN2をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL1 = 0;  //AN1をMUXAでスキャンしない (参考)1: スキャンする 
        AD1CSSLbits.CSSL0 = 1;  //AN0をMUXAでスキャンする (参考)0: スキャンしない     ★使用するAN0のチャンネルだけ読み込む


                lcd_init();                             // LCD初期化
        lcd_cmd(0b00001100);    // カーソル:OFF  ブリンク:OFF

        lcd_clear();            // 全消去
                sprintf(Buf,"ADC Start !!");//C30とは異なり、arguement 不要
  

       lcd_str(Buf);                   //液晶表示 


        OpenTimer1(     T1_ON | //      タイマ1 イネーブル  //T1_OFF → タイマ1 ディセーブル
                                T1_SOURCE_INT | //クロックソース:インターナル //T1_SOURCE_EXT → 外部発振器
                                T1_PS_1_256,    //プリスケール 1/256   //1/1、1/2、1/4、1/8、1/16、1/32、1/64、1/256
                                31249   //PRx値:  T0[msec] = 1000/80000000*256*31249 =99.9968 msec
                                                //PICMX32は1クロックで1命令
                                                //周期 T0[sec] = 1/Fosc × プリスケーラの逆数 × PRx値
                                );
        ConfigIntTimer1(T1_INT_ON | T1_INT_PRIOR_2);    //タイマ1割込ON、割り込みレベル2
        INTEnableSystemMultiVectoredInt();      //割り込みをマルチベクタモードで許可

        while(1)
        {
        }

}


//*************************************************************************
//インクルードファイル    1lcd_lib_C32.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//*************************************************************************

#include <proc/p32mx460f512l.h>         //PIC32MX460F512L

#define Clock   80000000        // 単位はHzで指定


// LCDポート設定
#define lcd_port_DB7    LATEbits.LATE7  //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6    LATEbits.LATE6  //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5    LATEbits.LATE5  //LCDのDB5(12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4    LATEbits.LATE4  //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_stb                 LATEbits.LATE3  //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定  
#define lcd_rs                  LATEbits.LATE2  //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定


void lcd_out(char code, char flag);
void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_str(char *str);




//**************************************************************************
//インクルードファイル    1lcd_lib_C32.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//**************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C32コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//    lcd_str(str*) ----- 文字列表示 
//////////////////////////////////////////////

#include        "1lcd_lib_C32.h"

void lcd_delay_us(unsigned int usec)    //1μsec遅延関数
{
        int count;

        count = (int)(Clock/20000000)*usec;
        do
        {
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                count--;        
        }while(count != 0);
}

void lcd_delay_ms(unsigned int msec)    //1msec遅延関数
{
        unsigned int i;
        
        for(i=0; i<msec; i++)
        lcd_delay_us(1000);
}


//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;

        if (flag == 0)
                lcd_rs = 1;                     // 表示データの場合
        else
                lcd_rs = 0;                     // コマンドデータの場合

        lcd_delay_us(1);                //1μsecウェイト
                
        lcd_stb = 1;                    // strobe(E) ON (Enable)
                        
        lcd_delay_us(1);                // 1μsec : strobe信号の幅

        lcd_stb = 0;                    // reset strobe
}

//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);               // 上位4ビット出力
        lcd_out(asci<<4, 0);    // 下位4ビット出力
        lcd_delay_us(50);               //50μsecウェイト
}

/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                // 上位4ビット出力
        lcd_out(cmd<<4, 1);             // 下位4ビット出力
        if((cmd & 0x03) != 0)   // clear Homeの場合
        lcd_delay_ms(2);        //      2msec待ち
        else
        lcd_delay_us(50);       //50μsecウェイト    
}

/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  // 初期化コマンド出力
}

/////// 文字列出力関数
void lcd_str(char* str)      
{
        while(*str)                             //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;                          //ポインタをインクリメント                          
        }       
}


/////// 初期化関数
void lcd_init(void)
{
        lcd_delay_ms(20);               //20msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(5);                //5msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_out(0x20, 1);               // 4bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_cmd(0x2E);                  // DL=0 4bit mode
        lcd_cmd(0x08);                  // display off C=D=B=0
        lcd_cmd(0x0D);                  // display on C=D=1 B=0
        lcd_cmd(0x06);                  // entry I/D=1 S=0
        lcd_cmd(0x02);                  // cursor home
}



<動作結果>
 液晶の下に写っているのはAN0の端子電圧を表示しているデジタルテスターです。

AN0の入力電圧
0V 1.5V 3.3V



■ XC32コンパイラ PIC32MZ編
  PIC32MZのADモジュールは PIC32MXとはその構成が大幅に変更になっています。 その為か revision 5 になってようやく 動くようになったようです。
 シリコンチップをつくることは はたで思うよりはるかに難しいようです。

 PIC32MZ2048ECH100の内臓ADコンバータからAD変換値を読込み、値を液晶に表示した例を紹介します。


 <試作品仕様>
  ・ PIC32MZ2048ECH100のAN25端子から内臓AD変換器をつかい電圧を読み込む
  ・ リファレンス電圧は+3.3V(PICの電源電圧)とする。
  ・ 液晶には以下を100msec毎に表示する。
     @ 1行目 …… AD変換値
     A 2行目 …… 入力電圧(単位:ボルト)
  ・ 開発環境 ……  Harmony: ver. 1.02   XC32: ver.1.34    MPLABX: ver.2.26    PIC32MZ2048ECH100: revision 5


 <試作品回路図>
  PIC32MZ2048ECH100の場合の回路図を以下にしめします。(→回路図のPDFファイル


<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています

     

          

   <プログラム例>
//以下、 main.c 
//--------------------------------------------------------------------------------------------------------
/*******************************************************************************
  MPLAB Harmony Project Main Source File

  Company:
    Microchip Technology Inc.
  
  File Name:
    main.c

  Summary:
    This file contains the "main" function for an MPLAB Harmony project.

  Description:
    This file contains the "main" function for an MPLAB Harmony project.  The
    "main" function calls the "SYS_Initialize" function to initialize the state 
    machines of all MPLAB Harmony modules in the system and it calls the 
    "SYS_Tasks" function from within a system-wide "super" loop to maintain 
    their correct operation. These two functions are implemented in 
    configuration-specific files (usually "system_init.c" and "system_tasks.c")
    in a configuration-specific folder under the "src/system_config" folder 
    within this project's top-level folder.  An MPLAB Harmony project may have
    more than one configuration, each contained within it's own folder under
    the "system_config" folder.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

//Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include <stddef.h>                     // Defines NULL
#include <stdbool.h>                    // Defines true
#include <stdlib.h>                     // Defines EXIT_FAILURE
#include "system/common/sys_module.h"   // SYS function prototypes


// *****************************************************************************
// *****************************************************************************
// Section: Main Entry Point
// *****************************************************************************
// *****************************************************************************

int main ( void )
{
    /* Initialize all MPLAB Harmony modules, including application(s). */
    SYS_Initialize ( NULL );

    while ( true )
    {
        /* Maintain state machines of all polled MPLAB Harmony modules. */
        SYS_Tasks ( );

    }

    /* Execution should not come here during normal operation */

    return ( EXIT_FAILURE );
}


/*******************************************************************************
 End of File
*/





//以下、app.c
//---------------------------------------------------------------------------------------------------
/*******************************************************************************
  MPLAB Harmony Application Source File

  Company:
    Microchip Technology Inc.

  File Name:
    app.c

  Summary:
    This file contains the source code for the MPLAB Harmony application.

  Description:
    This file contains the source code for the MPLAB Harmony application.  It
    implements the logic of the application's state machine and it may call
    API routines of other MPLAB Harmony modules in the system, such as drivers,
    system services, and middleware.  However, it does not call any of the
    system interfaces (such as the "Initialize" and "Tasks" functions) of any of
    the modules in the system or make any assumptions about when those functions
    are called.  That is the responsibility of the configuration-specific system
    files.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include "app.h"



# ifndef _MY_INCLUDE_PERIPHERAL
#define   _MY_INCLUDE_PERIPHERAL
#include <peripheral/peripheral.h>
#include <peripheral/ports/plib_ports.h>
#endif

#include "adc_p32mz2048ech100.h"
#include "adcp_p32mz2048ech100.h"
#include "1lcd_lib_C32.h"

#define ADC_ID_1 0


int delay_Clock = 200000000;   //200MHz
char Buf[17];   //1液晶表示バッファー



extern int Flag_Adc;

void delay_us(volatile unsigned int usec)        //1μsec遅延
{
        volatile  int count;

        count = (int)(delay_Clock/20000000)*usec;


        do      //実測 at 200MH (Clock=200000000)
        {       //delay_us(1000):1000.4μsec  delay_us(100):100.6μsec  delay_us(10):10.5μsec  delay_us(1):1.5μsec
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");asm("NOP");
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

                count--;
        }while(count != 0);


}

void delay_ms(volatile unsigned int msec)        //1msec遅延
{
        volatile unsigned int i;         //実測:at200MH (Clock=200000000)//delay_ms(1): 1.0006msec   delay_ms(100):100.04msec

        for(i=0; i<msec; i++)
        delay_us(1000);
}


void AdcFunc(void)
{
    unsigned int AdcValue;
    float Volt;
    int I,F;

    //PLIB_ADCP_IndividualTrigger(ADCP_ID_1, ADCP_AN4);
    AD1CON3bits.RQCONVRT = 1;   //個別入力AD変換開始    //Individual ADC Input Conversion Request bit


     //AdcValue = PLIB_ADCP_ResultGet( ADC_ID_1, ADCP_AN4 );  //AN25用バッファから変換値(unsigned int) 読出し
    while(!AD1DSTAT1bits.ARDY4);   //AN4の変換終了待ち
    AdcValue = AD1DATA4;           //AN4用バッファから変換値(unsigned int) 読出し


    lcd_cmd(0x80);          //1目の先頭へ

    sprintf(Buf,"AdV=%u             ",AdcValue); //バッファーに文字列をセット
    lcd_str(Buf);       // 開始メッセージ1行目表示

    Volt =(float)AdcValue/2048*3.3;

    lcd_cmd(0xC0);          //2行目の先頭へ
    sprintf(Buf,"Volt=%.2f[V]",Volt);       //文字列としてバッファーに収納
    lcd_str(Buf);           // 開始メッセージ1行目表示


    Flag_Adc = 0;

}




// *****************************************************************************
// *****************************************************************************
// Section: Global Data Definitions
// *****************************************************************************
// *****************************************************************************

// *****************************************************************************
/* Application Data

  Summary:
    Holds application data

  Description:
    This structure holds the application's data.

  Remarks:
    This structure should be initialized by the APP_Initialize function.

    Application strings and buffers are be defined outside this structure.
*/

APP_DATA appData;


// *****************************************************************************
// *****************************************************************************
// Section: Application Callback Functions
// *****************************************************************************
// *****************************************************************************

/* TODO:  Add any necessary callback funtions.
*/


// *****************************************************************************
// *****************************************************************************
// Section: Application Local Functions
// *****************************************************************************
// *****************************************************************************

/* TODO:  Add any necessary local functions.
*/


// *****************************************************************************
// *****************************************************************************
// Section: Application Initialization and State Machine Functions
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void APP_Initialize ( void )

  Remarks:
    See prototype in app.h.
 */

void APP_Initialize ( void )
{
    /* Place the App state machine in its initial state. */
    appData.state = APP_STATE_INIT;

    /* TODO: Initialize your application's state machine and other
     * parameters.
     */


    //液晶ポート入出力設定-----------------------------
    PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_B, 15 );
    PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_B, 14 );
    PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_B, 13 );
    PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_B, 12 );
    PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_A, 10 );
    PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_A, 9 );
/*
    TRISBbits.TRISB15 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB14 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB13 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB12 = 0;       //キャラクタ液晶ポート設定
    TRISAbits.TRISA10 = 0;       //キャラクタ液晶ポート設定
    TRISAbits.TRISA9 = 0;       //キャラクタ液晶ポート設定
*/



    //ADCモジュールキャリブレーション
    PLIB_ADCP_Configure(ADCP_ID_1, ADCP_VREF_VREFP_VREFN, false, false, false,  //Reference voltage set to VREF positive and VREF negative
                                                                                //boostVref:false//fractionalOutputOn:false//stopInIdle:false
    ADCP_CLK_SRC_SYSCLK, (96000000/ 16000000 / 2), 32, 0, 32);                  //ADC TAD clock:96MHz//Desired TAD clock Frequency:16MHz
                                                                                //oversampleDigFilterSamTime:32//earlyIntEnable:0//class2and3SampleTime:32


    AD1CAL1 = 0xF8894530;  // Use software calibration values into AD1CALx
    AD1CAL2 = 0x01E4AF69;
    AD1CAL3 = 0x0FBBBBB8;
    AD1CAL4 = 0x000004AC;
    AD1CAL5 = 0x02000002;

    PLIB_ADCP_SHModeSelect(ADCP_ID_1, ADCP_SH0, ADCP_SH_MODE_DIFFERENTIAL_UNIPOLAR);//SH0モジュールを差動アンプモードに設定
    PLIB_ADCP_SHModeSelect(ADCP_ID_1, ADCP_SH1, ADCP_SH_MODE_DIFFERENTIAL_UNIPOLAR);//SH1モジュールを差動アンプモードに設定
    PLIB_ADCP_SHModeSelect(ADCP_ID_1, ADCP_SH2, ADCP_SH_MODE_DIFFERENTIAL_UNIPOLAR);//SH2モジュールを差動アンプモードに設定
    PLIB_ADCP_SHModeSelect(ADCP_ID_1, ADCP_SH3, ADCP_SH_MODE_DIFFERENTIAL_UNIPOLAR);//SH3モジュールを差動アンプモードに設定
    PLIB_ADCP_SHModeSelect(ADCP_ID_1, ADCP_SH4, ADCP_SH_MODE_DIFFERENTIAL_UNIPOLAR);//SH4モジュールを差動アンプモードに設定
    PLIB_ADCP_SHModeSelect(ADCP_ID_1, ADCP_SH5, ADCP_SH_MODE_DIFFERENTIAL_UNIPOLAR);//SH5モジュールを差動アンプモードに設定

    PLIB_ADCP_ChannelScanConfigure(ADCP_ID_1, 0, 0, ADCP_SCAN_TRG_SRC_TMR3_MATCH);

    PLIB_ADCP_Enable(ADCP_ID_1);    //ADC有効化、 シリコンチップキャリブレーションを実行//Turn on the ADC. Wait for silicon ADC self cal to finish
    while(!PLIB_ADCP_ModuleIsReady(ADCP_ID_1));  //ADC準備完了を待つ

    //アプリケーションでのADC設定
    //PLIB_ADCP_Disable(ADC_ID_1);
    AD1CON1bits.ADCEN = 0;

    //PLIB_ADCP_SHModeSelect(ADC_ID_1, ADCP_SH5, ADCP_SH_MODE_SINGLE_ENDED_UNIPOLAR);
    AD1IMODbits.SH5MOD = 0b00;  //No5SHを シングルエンド入力、出力ユニポーラエンコードの unsigned intに設定

     //PLIB_ADC_InputSelectPositive(ADC_ID_1, ADC_INPUT_POSITIVE_AN4);//未サポート関数
    AD1CON3bits.ADINSEL = 4;   //AD変換入力ポート AN4設定


     //PLIB_PORTS_PinDirectionInputSet( PORTS_ID_0, PORT_CHANNEL_B, 4 );
    TRISBbits.TRISB4 = 1;   //RB4 入力モード設定



    //PLIB_PORTS_PinModeSelect(PORTS_ID_0, PORTS_ANALOG_PIN_4, PORTS_PIN_MODE_ANALOG);
    ANSELBbits.ANSB4 = 1;    //RB4/AN4 アナログモード
  



    //PLIB_ADC_VoltageReferenceSelect(ADC_ID_1, ADC_REFERENCE_VDD_TO_AVSS ); ?   //リファレンス電圧設定: Vrefh = AVdd, Vrefl = AVss//未サポート関数
    AD1CON3bits.VREFSEL = 0b000;    //リファレンス電圧設定: Vrefh = AVdd, Vrefl = AVss

    //PLIB_ADC_ConversionClockSourceSelect(ADC_ID_1, ADC_CLOCK_SOURCE_SYSTEM_CLOCK); //未サポート関数
    AD1CON2bits.ADCSEL = 0b01;     //AD変換クロックソース:システムクロック(200MHz) //ADC Clock Source //System Clock
                                    //外部入力の場合 0b10: REFCLK3(PPS)   //内蔵高速クロック(8MHz)の場合0b11: FRC //0b00 = Reserved

    // PLIB_ADC_ConversionClockSet(ADC_ID_1, SYS_CLK_FREQUENCY, 19);  //This function sets the ADC module conversion clock prescaler//未サポート関数
    AD1CON2bits.ADCDIV = 19;     //AD変換クロック分周比:1/20  変換周波数:200MHz --> 10MHz (Tad = 100nsec)  // 1MHz < 10MHz < 16MHz  故 OK

    //PLIB_ADC_SampleAcqusitionTimeSet(ADC_ID_1, 50 );  //サンプル時間(アクイジション時間)50Tad//未サポート関数
    AD1CON2bits.SAMC = 50;   //サンプル時間(アクイジション時間)50Tad = 100nsec x 50 = 5000nec = 5μsec

    //PLIB_ADCP_Enable(ADC_ID_1); //PLIB_ADC_Enable(ADC_ID_1);   //ADC モジュール 有効   // Enable the ADC module
    AD1CON1bits.ADCEN = 1;    //ADC モジュール 有効





    lcd_init();                         // LCD初期化
    lcd_cmd(0b00001100);    // カーソル:OFF  ブリンク:OFF

    lcd_cmd(0x80);          //1目の先頭へ
    sprintf(Buf,"AD converter       ");//
    lcd_str(Buf);                   //液晶表示

    lcd_cmd(0xC0);          //2行目の先頭へ
    sprintf(Buf,"    Start !!    ");    //
    lcd_str(Buf);           // 開始メッセージ1行目表示

    delay_ms(2000);






}


/******************************************************************************
  Function:
    void APP_Tasks ( void )

  Remarks:
    See prototype in app.h.
 */

void APP_Tasks ( void )
{
    /* Check the application's current state. */
    switch ( appData.state )
    {
        /* Application's initial state. */
        case APP_STATE_INIT:
        {
            if(Flag_Adc == 1)AdcFunc();     //割込み発生時
            break;
        }

        /* TODO: implement your application state machine.*/

        /* The default state should never be executed. */
        default:
        {
            /* TODO: Handle error in application's state machine. */
            break;
        }
    }
}


/*******************************************************************************
 End of File
 */






//以下、system_init.c
//---------------------------------------------------------------------------------------------------

/*******************************************************************************
  System Initialization File

  File Name:
    system_init.c

  Summary:
    This file contains source code necessary to initialize the system.

  Description:
    This file contains source code necessary to initialize the system.  It
    implements the "SYS_Initialize" function, configuration bits, and allocates
    any necessary global system resources, such as the systemObjects structure
    that contains the object handles to all the MPLAB Harmony module objects in
    the system.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include "system_config.h"
#include "app.h"
#include "system_definitions.h"


// ****************************************************************************
// ****************************************************************************
// Section: Configuration Bits
// ****************************************************************************
// ****************************************************************************
//-----------------------------------------------------------------------
//DEVCFG0レジスタ
#pragma config EJTAGBEN = NORMAL
#pragma config DBGPER = ALLOW_PG2
#pragma config FSLEEP = OFF
#pragma config FECCCON = OFF_UNLOCKED
#pragma config BOOTISA = MIPS32
#pragma config TRCEN = OFF
#pragma config ICESEL = ICS_PGx2
#pragma config JTAGEN = OFF //JTAG ポート Disable
#pragma config DEBUG = OFF



//----------------------------------------------------------------------
//DEVCFG1レジスタ
#pragma config FNOSC = SPLL //PLL回路(システムPLL)選択   //システム発振回路 //内蔵FRC(8MHz)選択の場合:FNOSC = FRCDIV   //Oscillator Selection Bits (Fast RC Osc w/Div-by-N (FRCDIV))
#pragma config FDMTEN = OFF //デッドマンタイマ OFF (Deadman Timer is disabled)
//#pragma config DMTINTV = WIN_127_128 // DMT Count Window Interval (Window/Interval value is 127/128 counter value)

#pragma config FSOSCEN = OFF // 副発振器OFF   //Secondary Oscillator Enable (Disable SOSC)
#pragma config IESO = OFF //ウェイクアップ時の2段速度スタートアップ // Internal/External Switch Over (Disabled)

#pragma config POSCMOD = HS //HS: ハイスピードレゾネータモード // HS(High Speed Resonator Operation) Oscillator mode selected
                            //EC: 外部発振器    //EC(External Clock Input Operation) mode selected // Primary Oscillator Configuration (Primary osc disabled)
#pragma config OSCIOFNC = OFF //OSCCOピン出力無効
#pragma config FCKSM = CSECME   //クロック発振:切替及びモニタ有効  //主発振器失陥でFRC(内蔵高速発振器)に切替   //FSCM(Fail Safe Clock Monitor)制御

#pragma config FWDTEN = OFF // ウォッチドックタイマ OFF    //Watchdog Timer Disable
//#pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler (1:1048576)
//#pragma config WDTSPGM = STOP // Watchdog Timer Stop During Flash Programming (WDT stops during Flash programming)
//#pragma config WINDIS = NORMAL // Watchdog Timer Window Mode (Watchdog Timer is in non-Window mode)
//#pragma config FWDTWINSZ = WINSZ_25 // Watchdog Timer Window Size (Window size is 25%)



//--------------------------------------------------------------------------------------------------------------------
// DEVCFG2レジスタ
//システムクロック:200MHz
//ペリフェラル周波数://default: 100MHz    //PBxDIVで8系統毎に設定変更可
//PBxDIV: PERIPHERAL BUS CLOCK DIVISOR CONTROL レジスタのPBDIV<6:0>: Peripheral Bus Clock Divisor Control ビットで設定

#pragma config FPLLRNG = RANGE_13_26_MHZ        //PLL Input周波数入力範囲設定// System PLL Input Range (13-26 MHz Input)  //24MHz故
#pragma config FPLLIDIV = DIV_3 //PLL入力側での分周: 1/3  // PLL Input周波数 = 24MHz ÷ 3 = 8MHz     // System PLL Input Divider (1x Divider)

//#pragma config FPLLICLK = PLL_POSC //主発振回路選択 //内蔵FRC(8MHz)の場合はFPLLICLK = PLL_FRC//  System PLL Input Clock Selection (POSC is input to the System PLL)
#pragma config FPLLICLK = PLL_FRC   //内蔵高速発振器選択    //★★★ バグ有 主発振回路選択の時、FPLLICLK = PLL_POSCではなくFPLLICLK = PLL_FRCを選択する。(at ver.1.33 XC32)

#pragma config FPLLMULT = MUL_50 //PLL倍率:50倍 //8MHz x 50 = 400MHz  //System PLL Multiplier (PLL Multiply by 50)
#pragma config FPLLODIV = DIV_2 //PLL出力側での分周: 1/2  //システムクロック = 400MHz ÷ 2 = 200MHz


#pragma config UPLLFSEL = FREQ_24MHZ //USBのPLL入力を 24MHz→12MHzに変換 // USB PLL Input Frequency Selection (USB PLL input is 12 MHz)
#pragma config UPLLEN = ON //USBのPLL変換:イネーブル // USB PLL Enable (USB PLL is enabled)




//--------------------------------------------------------------------------------------------------------------------------
//DEVCFG3レジスタ
#pragma config USERID =     0xffff
#pragma config FMIIEN =     ON
#pragma config FETHIO =     ON
#pragma config PGL1WAY =    ON
#pragma config PMDL1WAY =   ON
#pragma config IOL1WAY =    ON
#pragma config FUSBIDIO =   ON




/*** BF1SEQ0 ***/

#pragma config TSEQ =       0xffff
#pragma config CSEQ =       0xffff


// *****************************************************************************
// *****************************************************************************
// Section: Library/Stack Initialization Data
// *****************************************************************************
// *****************************************************************************/



// *****************************************************************************
// *****************************************************************************
// Section: Driver Initialization Data
// *****************************************************************************
// *****************************************************************************




// *****************************************************************************
// *****************************************************************************
// Section: System Data
// *****************************************************************************
// *****************************************************************************

/* Structure to hold the object handles for the modules in the system. */
SYSTEM_OBJECTS sysObj;

// *****************************************************************************
// *****************************************************************************
// Section: Module Initialization Data
// *****************************************************************************
// *****************************************************************************

// *****************************************************************************
/* System Clock Initialization Data
*/

const SYS_CLK_INIT sysClkInit =
{
    .moduleInit = {0},
    .systemClockSource = SYS_CLK_SOURCE,
    .systemClockFrequencyHz = SYS_CLK_FREQ,
    .waitTillComplete = true,
    .secondaryOscKeepEnabled = true,
    .onWaitInstruction = SYS_CLK_ON_WAIT,
};


/*** System Device Control Initialization Data ***/

const SYS_DEVCON_INIT sysDevconInit =
{
    .moduleInit = {0},
};


// *****************************************************************************
// *****************************************************************************
// Section: Static Initialization Functions
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void DRV_TMR0_Initialize(void)

  Summary:
    Initializes Timer Driver Instance 0

  Remarks:
 */
void DRV_TMR0_Initialize(void)
{
    /* Setup TMR0 Instance */
    PLIB_TMR_Stop(TMR_ID_1); /* Disable Timer */
    PLIB_TMR_ClockSourceSelect(TMR_ID_1, TMR_CLOCK_SOURCE_PERIPHERAL_CLOCK); /* Select clock source */
    PLIB_TMR_PrescaleSelect(TMR_ID_1, TMR_PRESCALE_VALUE_256); /* Select prescalar value */
    PLIB_TMR_Mode16BitEnable(TMR_ID_1); /* Enable 16 bit mode */
    PLIB_TMR_Counter16BitClear(TMR_ID_1); /* Clear counter */
    PLIB_TMR_Period16BitSet(TMR_ID_1, 0); /*Set period */

    /* Setup Interrupt */
    PLIB_INT_SourceEnable(INT_ID_0, INT_SOURCE_TIMER_1);
    PLIB_INT_VectorPrioritySet(INT_ID_0, INT_VECTOR_T1, INT_PRIORITY_LEVEL1);
    PLIB_INT_VectorSubPrioritySet(INT_ID_0, INT_VECTOR_T1, INT_SUBPRIORITY_LEVEL0);


    PLIB_TMR_Period16BitSet(TMR_ID_1,9766);    //5 nsec x20  x 9766 x 256 =250.0096msec = 250msec
    PLIB_TMR_Start(TMR_ID_1);    //タイマスタート

}

// *****************************************************************************
// *****************************************************************************
// Section: System Initialization
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void SYS_Initialize ( SYS_INIT_DATA *data )

  Summary:
    Initializes the board, services, drivers, application and other modules.

  Remarks:
    See prototype in system/common/sys_module.h.
 */

void SYS_Initialize ( void* data )
{
    /* Core Processor Initialization */
    SYS_CLK_Initialize(&sysClkInit);
    sysObj.sysDevcon = SYS_DEVCON_Initialize(SYS_DEVCON_INDEX_0, (SYS_MODULE_INIT*)&sysDevconInit);
    SYS_DEVCON_PerformanceConfig(SYS_DEVCON_SYSTEM_CLOCK);


    SYS_DEVCON_SystemUnlock();

    PB3DIVbits.PBDIV = 0x13;  //19: タイマ1用ペリフェラルクロック: 1/20  --> 10MHz( = 200MHz/20) //PBCLK3 is SYSCLK divided by 10
 //   PB3DIVbits.PBDIV = 0x03;  //PBCLK3 is SYSCLK divided by 4

    SYS_DEVCON_SystemLock();

    /* System Services Initialization */
    SYS_INT_Initialize();

    /* Initialize Drivers */
    /* Timer Instanace 0 Call */
    DRV_TMR0_Initialize();


    /* Initialize System Services */

    /* Initialize Middleware */

    /* Enable Global Interrupts */
    SYS_INT_Enable();

    /* Initialize the Application */
    APP_Initialize();
}

/*******************************************************************************
 End of File
*/




//以下、 system_interrupt.c
//-----------------------------------------------------------------------------------------------------------------------

/*******************************************************************************
 System Interrupts File

  File Name:
    system_int.c

  Summary:
    Raw ISR definitions.

  Description:
    This file contains a definitions of the raw ISRs required to support the
    interrupt sub-system.

  Summary:
    This file contains source code for the interrupt vector functions in the
    system.

  Description:
    This file contains source code for the interrupt vector functions in the
    system.  It implements the system and part specific vector "stub" functions
    from which the individual "Tasks" functions are called for any modules
    executing interrupt-driven in the MPLAB Harmony system.

  Remarks:
    This file requires access to the systemObjects global data structure that
    contains the object handles to all MPLAB Harmony module objects executing
    interrupt-driven in the system.  These handles are passed into the individual
    module "Tasks" functions to identify the instance of the module to maintain.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2011-2014 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include <xc.h>
#include <sys/attribs.h>
#include "app.h"
#include "system_definitions.h"

# ifndef _MY_INCLUDE_PERIPHERAL
#define   _MY_INCLUDE_PERIPHERAL
#include <peripheral/peripheral.h>
#include <peripheral/ports/plib_ports.h>
#endif


int Flag_Adc = 0;    //AD変換フラグ


// *****************************************************************************
// *****************************************************************************
// Section: System Interrupt Vector Functions
// *****************************************************************************
// *****************************************************************************
void __ISR(_TIMER_1_VECTOR, ipl2) _IntHandlerDrvTmrInstance0(void)
{
     PLIB_INT_SourceFlagClear(INT_ID_0,INT_SOURCE_TIMER_1);//タイマ1割り込みフラグクリア
   //IFS0bits.T1IF= 0;    //タイマ1割り込みフラグクリア
     
    PLIB_TMR_Period16BitSet(TMR_ID_1,9766);    //5 nsec x20  x 9766 x 256 =250.0096msec = 250msec

    Flag_Adc = 1;


}


/*******************************************************************************
 End of File
*/




//以下、1lcd_lib_C32.h
//------------------------------------------------------------------------------------------------------------
//*************************************************************************
//インクルードファイル    1lcd_lib_C32.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//*************************************************************************
#include <p32xxxx.h>
#define lcd_Clock   200000000        // 単位はHzで指定


// LCDポート設定
#define lcd_port_DB7    LATBbits.LATB15 //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6    LATBbits.LATB14 //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5    LATBbits.LATB13 //のDB5(12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4    LATBbits.LATB12 //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_rs          LATAbits.LATA9  //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定
#define lcd_stb         LATAbits.LATA10 //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定



void lcd_out(char code, char flag);
void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_str(char *str);







//以下、1lcd_lib_C32.c
//----------------------------------------------------------------------------------------------------------------------
//**************************************************************************
//インクルードファイル    1lcd_lib_C32.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//**************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C32コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//    lcd_str(str*) ----- 文字列表示 
//////////////////////////////////////////////

#include        "1lcd_lib_C32.h"

void lcd_delay_us(unsigned int usec)    //1μsec遅延関数
{
        int count;

        count = (int)(lcd_Clock/20000000)*usec;

        do      //実測: at 200MH (Clock=200000000)
        {       //delay_us(1000)→1000.4μsec、 delay_us(100)→100.6μsec、delay_us(10)→10.5μsec、delay_us(1)→1.5μsec
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");asm("NOP");
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

                count--;
        }while(count != 0);
        

}

void lcd_delay_ms(unsigned int msec)    //1msec遅延関数
{
        unsigned int i;
        
        for(i=0; i<msec; i++)
        lcd_delay_us(1000);
}


//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;

        if (flag == 0)
                lcd_rs = 1;                     // 表示データの場合
        else
                lcd_rs = 0;                     // コマンドデータの場合

        lcd_delay_us(3);                //1μsecウェイト
//      lcd_delay_us(1);                //1μsecウェイト
                
        lcd_stb = 1;                    // strobe(E) ON (Enable)
        lcd_delay_us(3);                //1μsecウェイト
//      lcd_delay_us(1);                // 1μsec : strobe信号の幅

        lcd_stb = 0;                    // reset strobe
}

//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);               // 上位4ビット出力
        lcd_out(asci<<4, 0);    // 下位4ビット出力
        lcd_delay_us(50);               //50μsecウェイト
}

/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                // 上位4ビット出力
        lcd_out(cmd<<4, 1);             // 下位4ビット出力
        if((cmd & 0x03) != 0)   // clear Homeの場合
        lcd_delay_ms(2);        //      2msec待ち
        else
        lcd_delay_us(50);       //50μsecウェイト    
}

/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  // 初期化コマンド出力
}

/////// 文字列出力関数
void lcd_str(char* str)      
{
        while(*str)                             //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;                          //ポインタをインクリメント                          
        }       
}


/////// 初期化関数
void lcd_init(void)
{
        lcd_delay_ms(20);               //20msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(5);                //5msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_out(0x20, 1);               // 4bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_cmd(0x2E);                  // DL=0 4bit mode
        lcd_cmd(0x08);                  // display off C=D=B=0
        lcd_cmd(0x0D);                  // display on C=D=1 B=0
        lcd_cmd(0x06);                  // entry I/D=1 S=0
        lcd_cmd(0x02);                  // cursor home
}





 



<動作結果>

         AD入力電圧         液晶上段: ADコンバータ読込整数値
液晶下段: 電圧換算値

テスター表示: 電圧値[V]
Vin = 0v
Vin = 1v
Vin = 2v
Vin = 3v
Vin = 3.3v